Skip to content

Commit 23901dc

Browse files
authored
Fix data race, GitHub #1085 (#1088)
* Fix data race, GitHub #1085 * Fix *nix typos.
1 parent 275b9c1 commit 23901dc

File tree

1 file changed

+26
-33
lines changed

1 file changed

+26
-33
lines changed

Release/src/pplx/pplx.cpp

+26-33
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,8 @@
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

2520
namespace 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

5542
private:
56-
atomic_long _M_lock;
43+
std::atomic_flag _M_lock;
5744
};
5845

5946
typedef ::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

118110
private:
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

Comments
 (0)