403 s_postAlwaysSignals =
false;
409 return s_postAlwaysSignals;
417template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
423 return state & k_DISABLED_GEN_MASK;
426template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
429 FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
430 ::getValueRaw(Int64 state)
432 return (state >> k_AVAILABLE_SHIFT) - (state & k_BLOCKED_MASK);
435template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
437bool FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
438 ::hasAvailable(Int64 state)
440 return k_AVAILABLE_INC <= state;
443template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
445bool FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
446 ::hasBlockedThread(Int64 state)
448 return 0 != (state & k_BLOCKED_MASK);
451template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
453bool FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
454 ::isDisabled(Int64 state)
456 return 0 != (state & k_DISABLED_GEN_INC);
459template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
461bool FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
462 ::willHaveBlockedThread(Int64 state)
464 return (state >> k_AVAILABLE_SHIFT) < (state & k_BLOCKED_MASK);
468template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
469int FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
475 const Int64 disabledGen = disabledGeneration(initialState);
482 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
484 if (willHaveBlockedThread(state)) {
486 LockGuard<MUTEX> guard(&d_waitMutex);
492 state = ATOMIC_OP::addInt64NvAcqRel(
494 k_AVAILABLE_INC + k_BLOCKED_INC);
499 while ( !hasAvailable(state)
500 && disabledGen == disabledGeneration(state)) {
501 int rv = d_waitCondition.timedWait(&d_waitMutex, absTime);
503 ATOMIC_OP::addInt64AcqRel(&d_state, -k_BLOCKED_INC);
509 state = ATOMIC_OP::getInt64Acquire(&d_state);
512 if (hasAvailable(state)) {
513 state = ATOMIC_OP::addInt64NvAcqRel(
515 -(k_AVAILABLE_INC + k_BLOCKED_INC));
518 ATOMIC_OP::addInt64AcqRel(&d_state, -k_BLOCKED_INC);
526 if ( hasAvailable(state)
527 && !isDisabled(state)
528 && hasBlockedThread(state)) {
529 d_waitCondition.signal();
536 if ( hasAvailable(state)
537 && !isDisabled(state)
538 && hasBlockedThread(state)) {
540 LockGuard<MUTEX> guard(&d_waitMutex);
542 d_waitCondition.signal();
549template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
550int FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
555 const Int64 disabledGen = disabledGeneration(initialState);
562 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
564 if (willHaveBlockedThread(state)) {
566 LockGuard<MUTEX> guard(&d_waitMutex);
572 state = ATOMIC_OP::addInt64NvAcqRel(
574 k_AVAILABLE_INC + k_BLOCKED_INC);
579 while ( !hasAvailable(state)
580 && disabledGen == disabledGeneration(state)) {
581 int rv = d_waitCondition.wait(&d_waitMutex);
583 ATOMIC_OP::addInt64AcqRel(&d_state, -k_BLOCKED_INC);
586 state = ATOMIC_OP::getInt64Acquire(&d_state);
589 if (hasAvailable(state)) {
590 state = ATOMIC_OP::addInt64NvAcqRel(
592 -(k_AVAILABLE_INC + k_BLOCKED_INC));
595 ATOMIC_OP::addInt64AcqRel(&d_state, -k_BLOCKED_INC);
603 if ( hasAvailable(state)
604 && !isDisabled(state)
605 && hasBlockedThread(state)) {
606 d_waitCondition.signal();
613 if ( hasAvailable(state)
614 && !isDisabled(state)
615 && hasBlockedThread(state)) {
617 LockGuard<MUTEX> guard(&d_waitMutex);
619 d_waitCondition.signal();
627template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
629FastPostSemaphoreImpl<ATOMIC_OP, MUTEX, CONDITION, THREADUTIL>
632, d_waitCondition(clockType)
634 ATOMIC_OP::initInt64(&d_state, 0);
637template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
643, d_waitCondition(clockType)
649template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
652 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
654 while (
false == isDisabled(state)) {
655 const Int64 expState = state;
659 Int64 newState = (state & ~k_DISABLED_GEN_MASK) |
660 ((state + k_DISABLED_GEN_INC) & k_DISABLED_GEN_MASK);
662 state = ATOMIC_OP::testAndSwapInt64AcqRel(&d_state,
666 if (expState == state) {
677 d_waitCondition.broadcast();
690 while (isDisabled(state) && willHaveBlockedThread(state)) {
693 state = ATOMIC_OP::getInt64Acquire(&d_state);
697template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
700 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
702 while (isDisabled(state)) {
708 if (willHaveBlockedThread(state)) {
711 state = ATOMIC_OP::getInt64Acquire(&d_state);
714 const Int64 expState = state;
718 Int64 newState = (state & ~k_DISABLED_GEN_MASK) |
719 ((state + k_DISABLED_GEN_INC) & k_DISABLED_GEN_MASK);
721 state = ATOMIC_OP::testAndSwapInt64AcqRel(&d_state,
725 if (expState == state) {
732template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
736 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, k_AVAILABLE_INC);
742 usePostAlwaysSignalsMitigation()
743 || k_AVAILABLE_INC == (state & k_AVAILABLE_MASK))
744 && !isDisabled(state)
745 && hasBlockedThread(state)) {
755 d_waitCondition.signal();
759template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
764 Int64 v = k_AVAILABLE_INC * value;
765 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, v);
771 usePostAlwaysSignalsMitigation()
772 || v == (state & k_AVAILABLE_MASK))
773 && !isDisabled(state)
774 && hasBlockedThread(state)) {
784 d_waitCondition.signal();
788template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
795 Int64 v = k_AVAILABLE_INC * value;
796 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, v);
803 usePostAlwaysSignalsMitigation()
804 || v == (state & k_AVAILABLE_MASK)
805 || ( k_AVAILABLE_INC * available <= (state & k_AVAILABLE_MASK)
806 && blocked <= (state & k_BLOCKED_MASK)))
807 && !isDisabled(state)
808 && hasBlockedThread(state)) {
818 d_waitCondition.signal();
821 usePostAlwaysSignalsMitigation()
822 || v == (state & k_AVAILABLE_MASK))
823 &&
"redundant signal sent");
827template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
832 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
841 count = getValueRaw(state);
847 if (maximumToTake < count) {
848 count = maximumToTake;
851 state = ATOMIC_OP::testAndSwapInt64AcqRel(
854 state - k_AVAILABLE_INC * count);
855 }
while (state != expState);
857 return static_cast<int>(count);
860template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
864 return take(INT_MAX);
867template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
872 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, -k_AVAILABLE_INC);
874 if (isDisabled(state)) {
879 if (willHaveBlockedThread(state)) {
880 return timedWaitSlowPath(absTime, state);
886template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
890 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, -k_AVAILABLE_INC);
892 if (isDisabled(state)) {
897 if (willHaveBlockedThread(state)) {
899 return e_WOULD_BLOCK;
905template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
909 Int64 state = ATOMIC_OP::addInt64NvAcqRel(&d_state, -k_AVAILABLE_INC);
911 if (isDisabled(state)) {
916 if (willHaveBlockedThread(state)) {
917 return waitSlowPath(state);
924template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
933template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
938 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
940 return static_cast<int>((state & k_DISABLED_GEN_MASK)
941 >> k_DISABLED_GEN_SHIFT);
944template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
949 Int64 count = getValueRaw(ATOMIC_OP::getInt64Acquire(&d_state));
951 return static_cast<int>(count > 0 ? count : 0);
954template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
959 Int64 count = getValueRaw(ATOMIC_OP::getInt64Acquire(&d_state));
961 return static_cast<int>(count);
964template <
class ATOMIC_OP,
class MUTEX,
class CONDITION,
class THREADUTIL>
969 Int64 state = ATOMIC_OP::getInt64Acquire(&d_state);
971 return isDisabled(state);