1919#define SWIFT_RUNTIME_MUTEX_H
2020
2121#include < type_traits>
22+ #include < utility>
2223
2324#if __has_include(<unistd.h>)
2425#include < unistd.h>
@@ -211,10 +212,10 @@ class ConditionVariable {
211212 // /
212213 // / Precondition: Mutex not held by this thread, undefined otherwise.
213214 template <typename CriticalSection>
214- auto withLock (CriticalSection criticalSection)
215- -> decltype(criticalSection()) {
215+ auto withLock (CriticalSection && criticalSection)
216+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
216217 ScopedLock guard (*this );
217- return criticalSection ();
218+ return std::forward<CriticalSection>( criticalSection) ();
218219 }
219220
220221 // / Acquires lock before calling the supplied critical section. If critical
@@ -242,7 +243,7 @@ class ConditionVariable {
242243 // / Precondition: Mutex not held by this thread, undefined otherwise.
243244 template <typename CriticalSection>
244245 void withLockOrWait (ConditionVariable &condition,
245- CriticalSection criticalSection) {
246+ CriticalSection && criticalSection) {
246247 withLock ([&] {
247248 while (!criticalSection ()) {
248249 wait (condition);
@@ -266,11 +267,11 @@ class ConditionVariable {
266267 // / Precondition: Mutex not held by this thread, undefined otherwise.
267268 template <typename CriticalSection>
268269 auto withLockThenNotifyOne (ConditionVariable &condition,
269- CriticalSection criticalSection)
270- -> decltype(criticalSection()) {
270+ CriticalSection && criticalSection)
271+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
271272 return withLock ([&] {
272273 ScopedNotifyOne guard (condition);
273- return criticalSection ();
274+ return std::forward<CriticalSection>( criticalSection) ();
274275 });
275276 }
276277
@@ -290,11 +291,11 @@ class ConditionVariable {
290291 // / Precondition: Mutex not held by this thread, undefined otherwise.
291292 template <typename CriticalSection>
292293 auto withLockThenNotifyAll (ConditionVariable &condition,
293- CriticalSection criticalSection)
294- -> decltype(criticalSection()) {
294+ CriticalSection && criticalSection)
295+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
295296 return withLock ([&] {
296297 ScopedNotifyAll guard (condition);
297- return criticalSection ();
298+ return std::forward<CriticalSection>( criticalSection) ();
298299 });
299300 }
300301
@@ -389,10 +390,10 @@ class Mutex {
389390 // /
390391 // / Precondition: Mutex not held by this thread, undefined otherwise.
391392 template <typename CriticalSection>
392- auto withLock (CriticalSection criticalSection)
393- -> decltype(criticalSection()) {
393+ auto withLock (CriticalSection && criticalSection)
394+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
394395 ScopedLock guard (*this );
395- return criticalSection ();
396+ return std::forward<CriticalSection>( criticalSection) ();
396397 }
397398
398399 // / A stack based object that locks the supplied mutex on construction
@@ -613,10 +614,10 @@ class ReadWriteLock {
613614 // /
614615 // / Precondition: ReadWriteLock not held by this thread, undefined otherwise.
615616 template <typename CriticalSection>
616- auto withReadLock (CriticalSection criticalSection)
617- -> decltype(criticalSection()) {
617+ auto withReadLock (CriticalSection && criticalSection)
618+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
618619 ScopedReadLock guard (*this );
619- return criticalSection ();
620+ return std::forward<CriticalSection>( criticalSection) ();
620621 }
621622
622623 // / Acquires write lock before calling the supplied critical section and
@@ -633,10 +634,10 @@ class ReadWriteLock {
633634 // /
634635 // / Precondition: ReadWriteLock not held by this thread, undefined otherwise.
635636 template <typename CriticalSection>
636- auto withWriteLock (CriticalSection criticalSection)
637- -> decltype(criticalSection()) {
637+ auto withWriteLock (CriticalSection && criticalSection)
638+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
638639 ScopedWriteLock guard (*this );
639- return criticalSection ();
640+ return std::forward<CriticalSection>( criticalSection) ();
640641 }
641642
642643private:
@@ -683,7 +684,7 @@ class StaticConditionVariable {
683684#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
684685 constexpr
685686#endif
686- StaticMutex ()
687+ StaticMutex ()
687688 : Handle(MutexPlatformHelper::conditionStaticInit()) {
688689 }
689690
@@ -706,16 +707,16 @@ class StaticConditionVariable {
706707
707708 // / See Mutex::lock
708709 template <typename CriticalSection>
709- auto withLock (CriticalSection criticalSection)
710- -> decltype(criticalSection()) {
710+ auto withLock (CriticalSection && criticalSection)
711+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
711712 ScopedLock guard (*this );
712- return criticalSection ();
713+ return std::forward<CriticalSection>( criticalSection) ();
713714 }
714715
715716 // / See Mutex::withLockOrWait
716717 template <typename CriticalSection>
717718 void withLockOrWait (StaticConditionVariable &condition,
718- CriticalSection criticalSection) {
719+ CriticalSection && criticalSection) {
719720 withLock ([&] {
720721 while (!criticalSection ()) {
721722 wait (condition);
@@ -726,22 +727,22 @@ class StaticConditionVariable {
726727 // / See Mutex::withLockThenNotifyOne
727728 template <typename CriticalSection>
728729 auto withLockThenNotifyOne (StaticConditionVariable &condition,
729- CriticalSection criticalSection)
730- -> decltype(criticalSection()) {
730+ CriticalSection && criticalSection)
731+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
731732 return withLock ([&] {
732733 StaticConditionVariable::ScopedNotifyOne guard (condition);
733- return criticalSection ();
734+ return std::forward<CriticalSection>( criticalSection) ();
734735 });
735736 }
736737
737738 // / See Mutex::withLockThenNotifyAll
738739 template <typename CriticalSection>
739740 auto withLockThenNotifyAll (StaticConditionVariable &condition,
740- CriticalSection criticalSection)
741- -> decltype(criticalSection()) {
741+ CriticalSection && criticalSection)
742+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
742743 return withLock ([&] {
743744 StaticConditionVariable::ScopedNotifyAll guard (condition);
744- return criticalSection ();
745+ return std::forward<CriticalSection>( criticalSection) ();
745746 });
746747 }
747748
@@ -779,7 +780,7 @@ class StaticMutex {
779780#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
780781 constexpr
781782#endif
782- StaticMutex ()
783+ StaticMutex ()
783784 : Handle(MutexPlatformHelper::staticInit()) {
784785 }
785786
@@ -794,10 +795,10 @@ class StaticMutex {
794795
795796 // / See Mutex::lock
796797 template <typename CriticalSection>
797- auto withLock (CriticalSection criticalSection)
798- -> decltype(criticalSection()) {
798+ auto withLock (CriticalSection && criticalSection)
799+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
799800 ScopedLock guard (*this );
800- return criticalSection ();
801+ return std::forward<CriticalSection>( criticalSection) ();
801802 }
802803
803804 // / A stack based object that locks the supplied mutex on construction
@@ -830,7 +831,7 @@ class StaticReadWriteLock {
830831#if SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR
831832 constexpr
832833#endif
833- StaticReadWriteLock ()
834+ StaticReadWriteLock ()
834835 : Handle(ReadWriteLockPlatformHelper::staticInit()) {
835836 }
836837
@@ -858,18 +859,18 @@ class StaticReadWriteLock {
858859
859860 // / See ReadWriteLock::withReadLock
860861 template <typename CriticalSection>
861- auto withReadLock (CriticalSection criticalSection)
862- -> decltype(criticalSection()) {
862+ auto withReadLock (CriticalSection && criticalSection)
863+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
863864 StaticScopedReadLock guard (*this );
864- return criticalSection ();
865+ return std::forward<CriticalSection>( criticalSection) ();
865866 }
866867
867868 // / See ReadWriteLock::withWriteLock
868869 template <typename CriticalSection>
869- auto withWriteLock (CriticalSection criticalSection)
870- -> decltype(criticalSection()) {
870+ auto withWriteLock (CriticalSection && criticalSection)
871+ -> decltype(std::forward<CriticalSection>( criticalSection) ()) {
871872 StaticScopedWriteLock guard (*this );
872- return criticalSection ();
873+ return std::forward<CriticalSection>( criticalSection) ();
873874 }
874875
875876private:
@@ -895,7 +896,7 @@ class StaticUnsafeMutex {
895896#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
896897 constexpr
897898#endif
898- StaticUnsafeMutex ()
899+ StaticUnsafeMutex ()
899900 : Handle(MutexPlatformHelper::staticInit()) {
900901 }
901902
@@ -920,6 +921,16 @@ class StaticUnsafeMutex {
920921 // / - Ignores errors that may happen, undefined when an error happens.
921922 void unlock () { MutexPlatformHelper::unsafeUnlock (Handle); }
922923
924+ template <typename CriticalSection>
925+ auto withLock (CriticalSection &&criticalSection)
926+ -> decltype(std::forward<CriticalSection>(criticalSection)()) {
927+ ScopedLock guard (*this );
928+ return std::forward<CriticalSection>(criticalSection)();
929+ }
930+
931+ typedef ScopedLockT<StaticUnsafeMutex, false > ScopedLock;
932+ typedef ScopedLockT<StaticUnsafeMutex, true > ScopedUnlock;
933+
923934private:
924935 MutexHandle Handle;
925936};
@@ -943,6 +954,12 @@ class IndirectMutex {
943954
944955 bool try_lock () { return Ptr->try_lock (); }
945956
957+ template <typename CriticalSection>
958+ auto withLock (CriticalSection &&criticalSection)
959+ -> decltype(criticalSection()) {
960+ return Ptr->withLock (std::forward<CriticalSection>(criticalSection));
961+ }
962+
946963 // / A stack based object that locks the supplied mutex on construction
947964 // / and unlocks it on destruction.
948965 // /
0 commit comments