]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/fiber/src/condition_variable.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / fiber / src / condition_variable.cpp
index 010891ab3bb1d19f9979c24003e8ad6d945f0e19..0678ccc107ec57234d38e1bbd9f54bc142880d99 100644 (file)
@@ -17,26 +17,60 @@ namespace fibers {
 
 void
 condition_variable_any::notify_one() noexcept {
+    context * active_ctx = context::active();
     // get one context' from wait-queue
-    detail::spinlock_lock lk( wait_queue_splk_);
-    if ( wait_queue_.empty() ) {
-        return;
+    detail::spinlock_lock lk{ wait_queue_splk_ };
+    while ( ! wait_queue_.empty() ) {
+        context * ctx = & wait_queue_.front();
+        wait_queue_.pop_front();
+        std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+        if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+            // notify before timeout
+            intrusive_ptr_release( ctx);
+            // notify context
+            active_ctx->schedule( ctx);
+            break;
+        } else if ( static_cast< std::intptr_t >( 0) == expected) {
+            // no timed-wait op.
+            // notify context
+            active_ctx->schedule( ctx);
+            break;
+        } else {
+            // timed-wait op.
+            // expected == -1: notify after timeout, same timed-wait op.
+            // expected == <any>: notify after timeout, another timed-wait op. was already started
+            intrusive_ptr_release( ctx);
+            // re-schedule next
+        }
     }
-    context * ctx = & wait_queue_.front();
-    wait_queue_.pop_front();
-    // notify context
-    context::active()->set_ready( ctx);
 }
 
 void
 condition_variable_any::notify_all() noexcept {
+    context * active_ctx = context::active();
     // get all context' from wait-queue
-    detail::spinlock_lock lk( wait_queue_splk_);
+    detail::spinlock_lock lk{ wait_queue_splk_ };
     // notify all context'
     while ( ! wait_queue_.empty() ) {
         context * ctx = & wait_queue_.front();
         wait_queue_.pop_front();
-        context::active()->set_ready( ctx);
+        std::intptr_t expected = reinterpret_cast< std::intptr_t >( this);
+        if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) {
+            // notify before timeout
+            intrusive_ptr_release( ctx);
+            // notify context
+            active_ctx->schedule( ctx);
+        } else if ( static_cast< std::intptr_t >( 0) == expected) {
+            // no timed-wait op.
+            // notify context
+            active_ctx->schedule( ctx);
+        } else {
+            // timed-wait op.
+            // expected == -1: notify after timeout, same timed-wait op.
+            // expected == <any>: notify after timeout, another timed-wait op. was already started
+            intrusive_ptr_release( ctx);
+            // re-schedule next
+        }
     }
 }