7 #if defined(RESUMEF_USE_CUSTOM_SPINLOCK)
8 using spinlock = RESUMEF_USE_CUSTOM_SPINLOCK;
16 static const size_t MAX_ACTIVE_SPIN = 4000;
17 static const size_t MAX_YIELD_SPIN = 8000;
18 static const int FREE_VALUE = 0;
19 static const int LOCKED_VALUE = 1;
23 std::thread::id owner_thread_id;
40 if (!lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acq_rel))
44 assert(owner_thread_id != std::this_thread::get_id());
48 auto dt = std::chrono::milliseconds{ 1 };
51 while (lck.load(std::memory_order_relaxed) != FREE_VALUE)
53 if (spinCount < MAX_ACTIVE_SPIN)
57 else if (spinCount < MAX_YIELD_SPIN)
60 std::this_thread::yield();
64 std::this_thread::sleep_for(dt);
65 dt = (std::min)(std::chrono::milliseconds{ 128 }, dt * 2);
70 }
while (!lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acq_rel));
74 owner_thread_id = std::this_thread::get_id();
84 bool ret = lck.compare_exchange_strong(val, LOCKED_VALUE, std::memory_order_acq_rel);
87 if (ret) owner_thread_id = std::this_thread::get_id();
99 owner_thread_id = std::thread::id();
101 lck.store(FREE_VALUE, std::memory_order_release);
107 #ifndef DOXYGEN_SKIP_PROPERTY
110 template<
class _Ty,
class _Cont = std::vector<_Ty>>
111 struct _LockVectorAssembleT
116 _LockVectorAssembleT(_Cont& _LkN)
123 _Ty& operator[](
int _Idx)
127 void _Lock_ref(_Ty& _LkN)
const
131 bool _Try_lock_ref(_Ty& _LkN)
const
133 return _LkN.try_lock();
135 void _Unlock_ref(_Ty& _LkN)
const
141 std::this_thread::yield();
143 void _ReturnValue()
const;
145 U _ReturnValue(U v)
const;
148 template<
class _Ty,
class _Cont>
149 struct _LockVectorAssembleT<std::reference_wrapper<_Ty>, _Cont>
154 _LockVectorAssembleT(_Cont& _LkN)
161 std::reference_wrapper<_Ty> operator[](
int _Idx)
165 void _Lock_ref(std::reference_wrapper<_Ty> _LkN)
const
169 void _Unlock_ref(std::reference_wrapper<_Ty> _LkN)
const
173 bool _Try_lock_ref(std::reference_wrapper<_Ty> _LkN)
const
175 return _LkN.get().try_lock();
179 std::this_thread::yield();
181 void _ReturnValue()
const;
183 U _ReturnValue(U v)
const;
186 #define LOCK_ASSEMBLE_NAME(fnName) scoped_lock_range_##fnName
187 #define LOCK_ASSEMBLE_AWAIT(a) (a)
188 #define LOCK_ASSEMBLE_RETURN(a) return (a)
189 #include "without_deadlock_assemble.inl"
190 #undef LOCK_ASSEMBLE_NAME
191 #undef LOCK_ASSEMBLE_AWAIT
192 #undef LOCK_ASSEMBLE_RETURN
194 #endif //DOXYGEN_SKIP_PROPERTY
202 template<
class _Ty,
class _Cont = std::vector<_Ty>,
class _Assemble = detail::_LockVectorAssembleT<_Ty, _Cont>>
213 detail::scoped_lock_range_lock_impl::_Lock_range(_LA);
223 detail::scoped_lock_range_lock_impl::_Lock_range(_LA);
238 explicit batch_lock_t(std::adopt_lock_t, _Cont& locks_, _Assemble& la_)
250 detail::scoped_lock_range_lock_impl::_Unlock_locks(0, (
int)_LA.size(), _LA);
261 detail::scoped_lock_range_lock_impl::_Unlock_locks(0, (
int)_LA.size(), _LA);
280 , _LA(std::move(_Right._LA))
282 _Right._LkN =
nullptr;
293 _Right._LkN =
nullptr;
295 _LA = std::move(_Right._LA);