1414#include " stdafx.h"
1515
1616#if !defined(_WIN32) || CPPREST_FORCE_PPLX
17-
1817#include " pplx/pplx.h"
19-
20- // Disable false alarm code analyze warning
21- #if defined(_MSC_VER)
22- #pragma warning(disable : 26165 26110)
23- #endif
18+ #include < atomic>
2419
2520namespace pplx
2621{
@@ -36,24 +31,16 @@ class _Spin_lock
3631
3732 void lock ()
3833 {
39- if ( details::atomic_compare_exchange ( _M_lock, 1l , 0l ) != 0l )
34+ while ( _M_lock. test_and_set () )
4035 {
41- do
42- {
43- pplx::details::platform::YieldExecution ();
44-
45- } while (details::atomic_compare_exchange (_M_lock, 1l , 0l ) != 0l );
36+ pplx::details::platform::YieldExecution ();
4637 }
4738 }
4839
49- void unlock ()
50- {
51- // fence for release semantics
52- details::atomic_exchange (_M_lock, 0l );
53- }
40+ void unlock () { _M_lock.clear (); }
5441
5542private:
56- atomic_long _M_lock;
43+ std::atomic_flag _M_lock;
5744};
5845
5946typedef ::pplx::scoped_lock<_Spin_lock> _Scoped_spin_lock;
@@ -63,59 +50,65 @@ static struct _pplx_g_sched_t
6350{
6451 typedef std::shared_ptr<pplx::scheduler_interface> sched_ptr;
6552
66- _pplx_g_sched_t () { m_state = post_ctor; }
53+ _pplx_g_sched_t () { m_state. store ( post_ctor, std::memory_order_relaxed) ; }
6754
68- ~_pplx_g_sched_t () { m_state = post_dtor; }
55+ ~_pplx_g_sched_t () { m_state. store ( post_dtor, std::memory_order_relaxed) ; }
6956
7057 sched_ptr get_scheduler ()
7158 {
72- switch (m_state)
59+ sched_ptr result;
60+ switch (m_state.load (std::memory_order_relaxed))
7361 {
7462 case post_ctor:
7563 // This is the 99.9% case.
76-
77- if (!m_scheduler)
7864 {
7965 ::pplx::details::_Scoped_spin_lock lock (m_spinlock);
8066 if (!m_scheduler)
8167 {
8268 m_scheduler = std::make_shared<::pplx::default_scheduler_t >();
8369 }
84- }
8570
86- return m_scheduler;
71+ result = m_scheduler;
72+ } // unlock
73+
74+ break ;
8775 default :
8876 // This case means the global m_scheduler is not available.
8977 // We spin off an individual scheduler instead.
90- return std::make_shared<::pplx::default_scheduler_t >();
78+ result = std::make_shared<::pplx::default_scheduler_t >();
79+ break ;
9180 }
81+
82+ return result;
9283 }
9384
9485 void set_scheduler (sched_ptr scheduler)
9586 {
96- if (m_state == pre_ctor || m_state == post_dtor)
87+ const auto localState = m_state.load (std::memory_order_relaxed);
88+ if (localState == pre_ctor || localState == post_dtor)
9789 {
9890 throw invalid_operation (" Scheduler cannot be initialized now" );
9991 }
10092
10193 ::pplx::details::_Scoped_spin_lock lock (m_spinlock);
10294
103- if (m_scheduler != nullptr )
95+ if (m_scheduler)
10496 {
10597 throw invalid_operation (" Scheduler is already initialized" );
10698 }
10799
108100 m_scheduler = std::move (scheduler);
109101 }
110102
111- enum
103+ enum m_state_values
112104 {
113- pre_ctor = 0 ,
114- post_ctor = 1 ,
115- post_dtor = 2
116- } m_state ;
105+ pre_ctor,
106+ post_ctor,
107+ post_dtor
108+ };
117109
118110private:
111+ std::atomic<m_state_values> m_state;
119112 pplx::details::_Spin_lock m_spinlock;
120113 sched_ptr m_scheduler;
121114} _pplx_g_sched;
0 commit comments