Skip to content

Commit 8765be1

Browse files
committed
Iteration 2 on global c/d-tor fix
1 parent 963c03a commit 8765be1

File tree

3 files changed

+79
-38
lines changed

3 files changed

+79
-38
lines changed

Release/include/pplx/pplxlinux.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,6 @@ namespace platform
245245
{
246246
public:
247247
_PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param);
248-
249-
virtual ~apple_scheduler();
250248
};
251249
#else
252250
class linux_scheduler : public pplx::scheduler_interface
@@ -255,7 +253,7 @@ namespace platform
255253
_PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param);
256254
};
257255
#endif
258-
256+
259257
} // namespace details
260258

261259
/// <summary>

Release/src/pplx/apple/pplxapple.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,40 +31,36 @@
3131
#include "stdafx.h"
3232
#include "pplx/pplx.h"
3333

34-
// DEVNOTE:
34+
// DEVNOTE:
3535
// The use of mutexes is suboptimal for synchronization of task execution.
3636
// Given that scheduler implementations should use GCD queues, there are potentially better mechanisms available to coordinate tasks (such as dispatch groups).
3737

3838
namespace pplx
3939
{
4040

4141
namespace details {
42-
42+
4343
namespace platform
4444
{
4545
_PPLXIMP long GetCurrentThreadId()
4646
{
4747
pthread_t threadId = pthread_self();
4848
return (long)threadId;
4949
}
50-
50+
5151
void YieldExecution()
5252
{
5353
sleep(0);
5454
}
55-
55+
5656
} // namespace platform
57-
57+
5858
void apple_scheduler::schedule( TaskProc_t proc, void* param)
5959
{
6060
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
6161
dispatch_async_f(queue, param, proc);
6262
}
63-
64-
apple_scheduler::~apple_scheduler()
65-
{
66-
}
67-
63+
6864
} // namespace details
69-
70-
} // pplx
65+
66+
} // pplx

Release/src/pplx/pplx.cpp

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/***
22
* ==++==
33
*
4-
* Copyright (c) Microsoft Corporation. All rights reserved.
4+
* Copyright (c) Microsoft Corporation. All rights reserved.
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
77
* You may obtain a copy of the License at
88
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
9+
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -33,13 +33,13 @@
3333

3434
#include "pplx/pplx.h"
3535

36-
// Disable false alarm code analyze warning
36+
// Disable false alarm code analyze warning
3737
#pragma warning (disable : 26165 26110)
38-
namespace pplx
38+
namespace pplx
3939
{
4040

4141

42-
namespace details
42+
namespace details
4343
{
4444
/// <summary>
4545
/// Spin lock to allow for locks to be used in global scope
@@ -57,7 +57,7 @@ namespace details
5757
{
5858
if ( details::atomic_compare_exchange(_M_lock, 1l, 0l) != 0l )
5959
{
60-
do
60+
do
6161
{
6262
pplx::details::platform::YieldExecution();
6363

@@ -78,33 +78,80 @@ namespace details
7878
typedef ::pplx::scoped_lock<_Spin_lock> _Scoped_spin_lock;
7979
} // namespace details
8080

81-
static std::shared_ptr<pplx::scheduler_interface> *_M_Scheduler;
82-
static pplx::details::_Spin_lock _M_SpinLock;
81+
static struct _pplx_g_sched_t {
82+
typedef std::shared_ptr<pplx::scheduler_interface> sched_ptr;
8383

84-
_PPLXIMP std::shared_ptr<pplx::scheduler_interface> __cdecl get_ambient_scheduler()
85-
{
86-
if ( !_M_Scheduler)
84+
_pplx_g_sched_t()
85+
{
86+
m_state = post_ctor;
87+
}
88+
89+
~_pplx_g_sched_t()
90+
{
91+
m_state = post_dtor;
92+
}
93+
94+
sched_ptr get_scheduler()
8795
{
88-
::pplx::details::_Scoped_spin_lock _Lock(_M_SpinLock);
89-
if (!_M_Scheduler)
96+
switch (m_state)
9097
{
91-
_M_Scheduler = new std::shared_ptr<pplx::scheduler_interface>(std::make_shared< ::pplx::default_scheduler_t>());
98+
case post_ctor:
99+
// This is the 99.9% case.
100+
101+
if (!m_scheduler)
102+
{
103+
::pplx::details::_Scoped_spin_lock lock(m_spinlock);
104+
if (!m_scheduler)
105+
{
106+
m_scheduler = std::make_shared< ::pplx::default_scheduler_t>();
107+
}
108+
}
109+
110+
return m_scheduler;
111+
case pre_ctor:
112+
case post_dtor:
113+
default:
114+
// This case means the global m_scheduler is not available.
115+
// We spin off an individual scheduler instead.
116+
return std::make_shared< ::pplx::default_scheduler_t>();
92117
}
93118
}
94119

95-
return *_M_Scheduler;
96-
}
120+
void set_scheduler(sched_ptr scheduler)
121+
{
122+
if (m_state == pre_ctor || m_state == post_dtor) {
123+
throw invalid_operation("Scheduler cannot be initialized now");
124+
}
97125

98-
_PPLXIMP void __cdecl set_ambient_scheduler(std::shared_ptr<pplx::scheduler_interface> _Scheduler)
99-
{
100-
::pplx::details::_Scoped_spin_lock _Lock(_M_SpinLock);
126+
::pplx::details::_Scoped_spin_lock lock(m_spinlock);
101127

102-
if (_M_Scheduler != nullptr)
103-
{
104-
throw invalid_operation("Scheduler is already initialized");
128+
if (m_scheduler != nullptr)
129+
{
130+
throw invalid_operation("Scheduler is already initialized");
131+
}
132+
133+
m_scheduler = std::move(scheduler);
105134
}
106135

107-
_M_Scheduler = new std::shared_ptr<pplx::scheduler_interface>(std::move(_Scheduler));
136+
enum {
137+
pre_ctor = 0,
138+
post_ctor = 1,
139+
post_dtor = 2
140+
} m_state;
141+
142+
private:
143+
pplx::details::_Spin_lock m_spinlock;
144+
sched_ptr m_scheduler;
145+
} _pplx_g_sched;
146+
147+
_PPLXIMP std::shared_ptr<pplx::scheduler_interface> __cdecl get_ambient_scheduler()
148+
{
149+
return _pplx_g_sched.get_scheduler();
150+
}
151+
152+
_PPLXIMP void __cdecl set_ambient_scheduler(std::shared_ptr<pplx::scheduler_interface> _Scheduler)
153+
{
154+
_pplx_g_sched.set_scheduler(std::move(_Scheduler));
108155
}
109156

110157
} // namespace pplx

0 commit comments

Comments
 (0)