1
1
/* **
2
2
* ==++==
3
3
*
4
- * Copyright (c) Microsoft Corporation. All rights reserved.
4
+ * Copyright (c) Microsoft Corporation. All rights reserved.
5
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
6
* you may not use this file except in compliance with the License.
7
7
* You may obtain a copy of the License at
8
8
* http://www.apache.org/licenses/LICENSE-2.0
9
- *
9
+ *
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33
33
34
34
#include " pplx/pplx.h"
35
35
36
- // Disable false alarm code analyze warning
36
+ // Disable false alarm code analyze warning
37
37
#pragma warning (disable : 26165 26110)
38
- namespace pplx
38
+ namespace pplx
39
39
{
40
40
41
41
42
- namespace details
42
+ namespace details
43
43
{
44
44
// / <summary>
45
45
// / Spin lock to allow for locks to be used in global scope
@@ -57,7 +57,7 @@ namespace details
57
57
{
58
58
if ( details::atomic_compare_exchange (_M_lock, 1l , 0l ) != 0l )
59
59
{
60
- do
60
+ do
61
61
{
62
62
pplx::details::platform::YieldExecution ();
63
63
@@ -78,33 +78,80 @@ namespace details
78
78
typedef ::pplx::scoped_lock<_Spin_lock> _Scoped_spin_lock;
79
79
} // namespace details
80
80
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 ;
83
83
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 ()
87
95
{
88
- ::pplx::details::_Scoped_spin_lock _Lock (_M_SpinLock);
89
- if (!_M_Scheduler)
96
+ switch (m_state)
90
97
{
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 >();
92
117
}
93
118
}
94
119
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
+ }
97
125
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);
101
127
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);
105
134
}
106
135
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));
108
155
}
109
156
110
157
} // namespace pplx
0 commit comments