- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我引用了Lewiss Baker的协程教程中的代码。
https://lewissbaker.github.io/2017/11/17/understanding-operator-co-await
bool async_manual_reset_event::awaiter::await_suspend(
std::experimental::coroutine_handle<> awaitingCoroutine) noexcept
{
// Special m_state value that indicates the event is in the 'set' state.
const void* const setState = &m_event;
// Remember the handle of the awaiting coroutine.
m_awaitingCoroutine = awaitingCoroutine;
// Try to atomically push this awaiter onto the front of the list.
void* oldValue = m_event.m_state.load(std::memory_order_acquire);
do
{
// Resume immediately if already in 'set' state.
if (oldValue == setState) return false;
// Update linked list to point at current head.
m_next = static_cast<awaiter*>(oldValue);
// Finally, try to swap the old list head, inserting this awaiter
// as the new list head.
} while (!m_event.m_state.compare_exchange_weak(
oldValue,
this,
std::memory_order_release,
std::memory_order_acquire));
// Successfully enqueued. Remain suspended.
return true;
}
std::atomic<void *>
。
bool async_manual_reset_event::is_set() const noexcept
{
return m_state.load(std::memory_order_acquire) == this;
}
void async_manual_reset_event::reset() noexcept
{
void* oldValue = this;
m_state.compare_exchange_strong(oldValue, nullptr, std::memory_order_acquire);
}
void async_manual_reset_event::set() noexcept
{
// Needs to be 'release' so that subsequent 'co_await' has
// visibility of our prior writes.
// Needs to be 'acquire' so that we have visibility of prior
// writes by awaiting coroutines.
void* oldValue = m_state.exchange(this, std::memory_order_acq_rel);
if (oldValue != this)
{
// Wasn't already in 'set' state.
// Treat old value as head of a linked-list of waiters
// which we have now acquired and need to resume.
auto* waiters = static_cast<awaiter*>(oldValue);
while (waiters != nullptr)
{
// Read m_next before resuming the coroutine as resuming
// the coroutine will likely destroy the awaiter object.
auto* next = waiters->m_next;
waiters->m_awaitingCoroutine.resume();
waiters = next;
}
}
}
m_state.exchange
方法的
set()
中,上面的注释清楚地说明了为什么调用交换需要获取和释放。
m_state.compare_exchange_weak
方法的
await_suspend()
中,第三个参数是std::memory_order_release但不是memory_order_acq_rel(获取已删除)。
struct lock {
uint64_t exclusive : 1;
uint64_t id : 48;
uint64_t shared_count : 15;
};
std::atomic<lock> lock_ { {0, 0, 0} };
bool try_lock_shared() noexcept {
lock currentlock = lock_.load(std::memory_order_acquire);
if (currentlock.exclusive == 1) {
return false;
}
lock newlock;
do {
newlock = currentlock;
newlock.shared_count++;
}
while(!lock_.compare_exchange_weak(currentlock, newlock, std::memory_order_acq_rel) && currentlock.exclusive == 0);
return currentlock.exclusive == 0;
}
bool try_lock() noexcept {
uint64_t id = utils::get_thread_id();
lock currentlock = lock_.load(std::memory_order_acquire);
if (currentlock.exclusive == 1) {
assert(currentlock.id != id);
return false;
}
bool result = false;
lock newlock { 1, id, 0 };
do {
newlock.shared_count = currentlock.shared_count;
}
while(!(result = lock_.compare_exchange_weak(currentlock, newlock, std::memory_order_acq_rel)) && currentlock.exclusive == 0);
return result;
}
lock_.compare_exchange_weak(currentlock, newlock, std::memory_order_acq_rel)
,可以安全地将它们替换为
compare_exchange_weak(currentlock, newlock, std::memory_order_release, std::memory_order_acquire)
吗?
memory_order_release
中删除
compare_exchange_strong
的示例(请参阅Lewis代码的
compare_exchange_strong
函数中的
reset()
),在这里您只需要std::memory_order_acquire作为compare_exchange_strong(但不发布)。我没有真正看到从弱函数中删除了memory_order_release也不从强函数中删除了memory_order_acquire。
最佳答案
memory_order_acquire
仅对读取值的操作有意义,而memory_order_release
仅对写入值的操作有意义。由于读-修改-写操作可以读写,因此可以合并这些存储顺序,但并非总是必要的。m_event.m_state.compare_exchange_weak
使用memory_order_release
写入新值,因为它试图替换以前使用memory_order_acquire读取的值:
// load initial value using memory_order_acquire
void* oldValue = m_event.m_state.load(std::memory_order_acquire);
do {
...
} while (!m_event.m_state.compare_exchange_weak(oldValue, this,
std::memory_order_release,
// in case of failure, load new value using memory_order_acquire
std::memory_order_acquire));
async_manual_reset_event::set()
中,情况不同:
void* oldValue = m_state.exchange(this, std::memory_order_acq_rel);
if (oldValue != this)
{
auto* waiters = static_cast<awaiter*>(oldValue);
while (waiters != nullptr)
{
// we are de-referencing the pointer read from m_state!
auto* next = waiters->m_next;
waiters->m_awaitingCoroutine.resume();
waiters = next;
}
m_state
读取的指针,所以我们必须确保这些读取在写入这些服务对象之后发生。这是通过
m_state
上的sync-with关系来确保的。通过
memory_order_release
通过前面讨论的compare_exchange添加了writer。交换的获取部分与release-compare_exchange(实际上是释放序列的一部分,所有先前的release-compare_exchange)同步,从而提供了必要的事前发生关系。
await_suspend
不需要memory_order_acquire,
is_set
和
reset
也是一样)。
try_lock_shared
/
try_lock
)时,仅将
memory_order_acquire
用于比较交换操作。释放锁必须使用
memory_order_release
。
try_lock
(acquire-CAS)与先前的
unlock
(发行商店)之间建立同步关系来实现的。
// (1) - this acquire-load synchronizes-with the release-CAS (11)
auto n = head.load(std::memory_order_acquire);
// (8) - this acquire-load synchronizes-with the release-CAS (11)
h.acquire(head, std::memory_order_acquire);
// (11) - this release-CAS synchronizes-with the acquire-load (1, 8)
if (head.compare_exchange_weak(expected, next, std::memory_order_release, std::memory_order_relaxed))
关于c++ - 什么时候可以安全地从compare_exchange中删除memory_order_acquire或memory_order_release?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61493121/
根据 Antony Williams 的书C++ Concurrency in Action,自旋锁可以按如下方式实现: class spinlock_mutex { std::atomic_fl
我最近了解了c++的六个内存顺序,我对memory_order_acquire和memory_order_release感到非常困惑,这是cpp的示例: #include #include #in
这个问题具体是关于引用计数指针中的普通可破坏类型。请参阅 Boost's documentation 中的示例关于原子的使用。 递减如下: if (x->refcount_.fetch_sub(1,
我一直在研究 C++ 11 中的内存顺序语义,但在理解 memory_order_acquire 在 CPU 级别的工作原理时遇到了一些困难。 根据cppreference; A load opera
我有一个关于 GCC-Wiki article 的问题.在标题“Overall Summary”下,给出了以下代码示例: 线程 1: y.store (20); x.store (10); 线程 2:
cppreference表示 std::memory_order_acquire 将阻止读取和写入在它之前重新排序。所以我可以使用 std::memory_order_acquire 只是为了防止在运
http://en.cppreference.com/w/cpp/atomic/memory_order和其他 C++11 在线引用资料,将 memory_order_acquire 和 memory
众所周知,在 x86 上,操作 load() 和 store() 内存屏障 memory_order_consume, memory_order_acquire, memory_order_relea
我对以下代码有疑问 #include #include #include std::atomic x, y; std::atomic z; void write_x_then_y() {
我想知道如果您有 2 个线程使用 memory_order_acquire 进行加载,一个线程使用 memory_acquire_release 进行存储,加载是否只会与两个执行加载的线程之一同步?意
我正在阅读 the documentation更具体地说 memory_order_acquire: A load operation with this memory order performs
我是一名优秀的程序员,十分优秀!