MCPcopy Create free account
hub / github.com/cameron314/readerwriterqueue / LightweightSemaphore

Class LightweightSemaphore

atomicops.h:669–725  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

667 // LightweightSemaphore
668 //---------------------------------------------------------
669 class LightweightSemaphore
670 {
671 public:
672 typedef std::make_signed<std::size_t>::type ssize_t;
673
674 private:
675 weak_atomic<ssize_t> m_count;
676 Semaphore m_sema;
677
678 bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1) AE_NO_TSAN
679 {
680 ssize_t oldCount;
681 // Is there a better way to set the initial spin count?
682 // If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC,
683 // as threads start hitting the kernel semaphore.
684 int spin = 1024;
685 while (--spin >= 0)
686 {
687 if (m_count.load() > 0)
688 {
689 m_count.fetch_add_acquire(-1);
690 return true;
691 }
692 compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop.
693 }
694 oldCount = m_count.fetch_add_acquire(-1);
695 if (oldCount > 0)
696 return true;
697 if (timeout_usecs < 0)
698 {
699 if (m_sema.wait())
700 return true;
701 }
702 if (timeout_usecs > 0 && m_sema.timed_wait(static_cast<uint64_t>(timeout_usecs)))
703 return true;
704 // At this point, we've timed out waiting for the semaphore, but the
705 // count is still decremented indicating we may still be waiting on
706 // it. So we have to re-adjust the count, but only if the semaphore
707 // wasn't signaled enough times for us too since then. If it was, we
708 // need to release the semaphore too.
709 while (true)
710 {
711 oldCount = m_count.fetch_add_release(1);
712 if (oldCount < 0)
713 return false; // successfully restored things to the way they were
714 // Oh, the producer thread just signaled the semaphore after all. Try again:
715 oldCount = m_count.fetch_add_acquire(-1);
716 if (oldCount > 0 && m_sema.try_wait())
717 return true;
718 }
719 }
720
721 public:
722 AE_NO_TSAN LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount), m_sema()
723 {
724 assert(initialCount >= 0);
725 }
726

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected