Browse code

Adding more win stuff

Steffen Neumann authored on 27/11/2021 11:11:29
Showing12 changed files

1 1
new file mode 100755
... ...
@@ -0,0 +1,176 @@
1
+#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
2
+#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
3
+
4
+//  basic_recursive_mutex.hpp
5
+//
6
+//  (C) Copyright 2006-8 Anthony Williams
7
+//  (C) Copyright 2011-2012,2017-2018 Vicente J. Botet Escriba
8
+//
9
+//  Distributed under the Boost Software License, Version 1.0. (See
10
+//  accompanying file LICENSE_1_0.txt or copy at
11
+//  http://www.boost.org/LICENSE_1_0.txt)
12
+
13
+#include <boost/thread/win32/thread_primitives.hpp>
14
+#include <boost/thread/win32/basic_timed_mutex.hpp>
15
+#ifdef BOOST_THREAD_USES_CHRONO
16
+#include <boost/chrono/system_clocks.hpp>
17
+#include <boost/chrono/ceil.hpp>
18
+#endif
19
+
20
+#include <boost/config/abi_prefix.hpp>
21
+
22
+namespace boost
23
+{
24
+    namespace detail
25
+    {
26
+        template<typename underlying_mutex_type>
27
+        struct basic_recursive_mutex_impl
28
+        {
29
+            long recursion_count;
30
+            long locking_thread_id;
31
+            underlying_mutex_type mutex;
32
+
33
+            void initialize()
34
+            {
35
+                recursion_count=0;
36
+                locking_thread_id=0;
37
+                mutex.initialize();
38
+            }
39
+
40
+            void destroy()
41
+            {
42
+                mutex.destroy();
43
+            }
44
+
45
+            bool try_lock() BOOST_NOEXCEPT
46
+            {
47
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
48
+                return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
49
+            }
50
+
51
+            void lock()
52
+            {
53
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
54
+                if(!try_recursive_lock(current_thread_id))
55
+                {
56
+                    mutex.lock();
57
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
58
+                    recursion_count=1;
59
+                }
60
+            }
61
+#if defined BOOST_THREAD_USES_DATETIME
62
+            bool timed_lock(::boost::system_time const& target)
63
+            {
64
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
65
+                return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
66
+            }
67
+            template<typename Duration>
68
+            bool timed_lock(Duration const& target)
69
+            {
70
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
71
+                return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
72
+            }
73
+#endif
74
+
75
+#ifdef BOOST_THREAD_USES_CHRONO
76
+            template <class Rep, class Period>
77
+            bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
78
+            {
79
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
80
+                return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
81
+            }
82
+            template <class Clock, class Duration>
83
+            bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
84
+            {
85
+                long const current_thread_id=boost::winapi::GetCurrentThreadId();
86
+                return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
87
+            }
88
+#endif
89
+            void unlock()
90
+            {
91
+                if(!--recursion_count)
92
+                {
93
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0);
94
+                    mutex.unlock();
95
+                }
96
+            }
97
+
98
+        private:
99
+            bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
100
+            {
101
+                if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
102
+                {
103
+                    ++recursion_count;
104
+                    return true;
105
+                }
106
+                return false;
107
+            }
108
+
109
+            bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
110
+            {
111
+                if(mutex.try_lock())
112
+                {
113
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
114
+                    recursion_count=1;
115
+                    return true;
116
+                }
117
+                return false;
118
+            }
119
+
120
+#if defined BOOST_THREAD_USES_DATETIME
121
+            bool try_timed_lock(long current_thread_id,::boost::system_time const& target)
122
+            {
123
+                if(mutex.timed_lock(target))
124
+                {
125
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
126
+                    recursion_count=1;
127
+                    return true;
128
+                }
129
+                return false;
130
+            }
131
+            template<typename Duration>
132
+            bool try_timed_lock(long current_thread_id,Duration const& target)
133
+            {
134
+                if(mutex.timed_lock(target))
135
+                {
136
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
137
+                    recursion_count=1;
138
+                    return true;
139
+                }
140
+                return false;
141
+            }
142
+#endif
143
+            template <typename TP>
144
+            bool try_timed_lock_until(long current_thread_id,TP const& target)
145
+            {
146
+                if(mutex.try_lock_until(target))
147
+                {
148
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
149
+                    recursion_count=1;
150
+                    return true;
151
+                }
152
+                return false;
153
+            }
154
+            template <typename D>
155
+            bool try_timed_lock_for(long current_thread_id,D const& target)
156
+            {
157
+                if(mutex.try_lock_for(target))
158
+                {
159
+                    BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
160
+                    recursion_count=1;
161
+                    return true;
162
+                }
163
+                return false;
164
+            }
165
+        };
166
+
167
+        typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;
168
+        typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex;
169
+    }
170
+}
171
+
172
+#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
173
+
174
+#include <boost/config/abi_suffix.hpp>
175
+
176
+#endif
0 177
new file mode 100755
... ...
@@ -0,0 +1,297 @@
1
+#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
2
+#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
3
+
4
+//  basic_timed_mutex_win32.hpp
5
+//
6
+//  (C) Copyright 2006-8 Anthony Williams
7
+//  (C) Copyright 2011-2012 Vicente J. Botet Escriba
8
+//
9
+//  Distributed under the Boost Software License, Version 1.0. (See
10
+//  accompanying file LICENSE_1_0.txt or copy at
11
+//  http://www.boost.org/LICENSE_1_0.txt)
12
+
13
+#include <boost/assert.hpp>
14
+#include <boost/thread/win32/thread_primitives.hpp>
15
+#include <boost/thread/win32/interlocked_read.hpp>
16
+#include <boost/thread/thread_time.hpp>
17
+#if defined BOOST_THREAD_USES_DATETIME
18
+#include <boost/thread/xtime.hpp>
19
+#endif
20
+#include <boost/detail/interlocked.hpp>
21
+#ifdef BOOST_THREAD_USES_CHRONO
22
+#include <boost/chrono/system_clocks.hpp>
23
+#include <boost/chrono/ceil.hpp>
24
+#endif
25
+#include <boost/thread/detail/platform_time.hpp>
26
+
27
+#include <boost/config/abi_prefix.hpp>
28
+
29
+namespace boost
30
+{
31
+    namespace detail
32
+    {
33
+        struct basic_timed_mutex
34
+        {
35
+            BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
36
+            BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
37
+            BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
38
+            BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
39
+            long active_count;
40
+            void* event;
41
+
42
+            void initialize()
43
+            {
44
+                active_count=0;
45
+                event=0;
46
+            }
47
+
48
+            void destroy()
49
+            {
50
+#ifdef BOOST_MSVC
51
+#pragma warning(push)
52
+#pragma warning(disable:4312)
53
+#endif
54
+                void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
55
+#ifdef BOOST_MSVC
56
+#pragma warning(pop)
57
+#endif
58
+                if(old_event)
59
+                {
60
+                    winapi::CloseHandle(old_event);
61
+                }
62
+            }
63
+
64
+            // Take the lock flag if it's available
65
+            bool try_lock() BOOST_NOEXCEPT
66
+            {
67
+                return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
68
+            }
69
+
70
+            void lock()
71
+            {
72
+                if(try_lock())
73
+                {
74
+                    return;
75
+                }
76
+                long old_count=active_count;
77
+                mark_waiting_and_try_lock(old_count);
78
+
79
+                if(old_count&lock_flag_value)
80
+                {
81
+                    void* const sem=get_event();
82
+
83
+                    do
84
+                    {
85
+                        if(winapi::WaitForSingleObjectEx(sem,::boost::detail::win32::infinite,0)==0)
86
+                        {
87
+                            clear_waiting_and_try_lock(old_count);
88
+                        }
89
+                    }
90
+                    while(old_count&lock_flag_value);
91
+                }
92
+            }
93
+
94
+            // Loop until the number of waiters has been incremented or we've taken the lock flag
95
+            // The loop is necessary since this function may be called by multiple threads simultaneously
96
+            void mark_waiting_and_try_lock(long& old_count)
97
+            {
98
+                for(;;)
99
+                {
100
+                    bool const was_locked=(old_count&lock_flag_value) ? true : false;
101
+                    long const new_count=was_locked?(old_count+1):(old_count|lock_flag_value);
102
+                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
103
+                    if(current==old_count)
104
+                    {
105
+                        if(was_locked)
106
+                            old_count=new_count;
107
+                        // else we've taken the lock flag
108
+                            // don't update old_count so that the calling function can see that
109
+                            // the old lock flag was 0 and know that we've taken the lock flag
110
+                        break;
111
+                    }
112
+                    old_count=current;
113
+                }
114
+            }
115
+
116
+            // Loop until someone else has taken the lock flag and cleared the event set flag or
117
+            // until we've taken the lock flag and cleared the event set flag and decremented the
118
+            // number of waiters
119
+            // The loop is necessary since this function may be called by multiple threads simultaneously
120
+            void clear_waiting_and_try_lock(long& old_count)
121
+            {
122
+                old_count&=~lock_flag_value;
123
+                old_count|=event_set_flag_value;
124
+                for(;;)
125
+                {
126
+                    long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
127
+                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
128
+                    if(current==old_count)
129
+                    {
130
+                        // if someone else has taken the lock flag
131
+                            // no need to update old_count since old_count == new_count (ignoring
132
+                            // event_set_flag_value which the calling function doesn't care about)
133
+                        // else we've taken the lock flag
134
+                            // don't update old_count so that the calling function can see that
135
+                            // the old lock flag was 0 and know that we've taken the lock flag
136
+                        break;
137
+                    }
138
+                    old_count=current;
139
+                }
140
+            }
141
+
142
+        private:
143
+            unsigned long getMs(detail::platform_duration const& d)
144
+            {
145
+                return static_cast<unsigned long>(d.getMs());
146
+            }
147
+
148
+            template <typename Duration>
149
+            unsigned long getMs(Duration const& d)
150
+            {
151
+                return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
152
+            }
153
+
154
+            template <typename Clock, typename Timepoint, typename Duration>
155
+            bool do_lock_until(Timepoint const& t, Duration const& max)
156
+            {
157
+                if(try_lock())
158
+                {
159
+                    return true;
160
+                }
161
+
162
+                long old_count=active_count;
163
+                mark_waiting_and_try_lock(old_count);
164
+
165
+                if(old_count&lock_flag_value)
166
+                {
167
+                    void* const sem=get_event();
168
+
169
+                    // If the clock is the system clock, it may jump while this function
170
+                    // is waiting. To compensate for this and time out near the correct
171
+                    // time, we call WaitForSingleObjectEx() in a loop with a short
172
+                    // timeout and recheck the time remaining each time through the loop.
173
+                    do
174
+                    {
175
+                        Duration d(t - Clock::now());
176
+                        if(d <= Duration::zero()) // timeout occurred
177
+                        {
178
+                            BOOST_INTERLOCKED_DECREMENT(&active_count);
179
+                            return false;
180
+                        }
181
+                        if(max != Duration::zero())
182
+                        {
183
+                            d = (std::min)(d, max);
184
+                        }
185
+                        if(winapi::WaitForSingleObjectEx(sem,getMs(d),0)==0)
186
+                        {
187
+                            clear_waiting_and_try_lock(old_count);
188
+                        }
189
+                    }
190
+                    while(old_count&lock_flag_value);
191
+                }
192
+                return true;
193
+            }
194
+        public:
195
+
196
+#if defined BOOST_THREAD_USES_DATETIME
197
+            bool timed_lock(::boost::system_time const& wait_until)
198
+            {
199
+                const detail::real_platform_timepoint t(wait_until);
200
+                return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
201
+            }
202
+
203
+            template<typename Duration>
204
+            bool timed_lock(Duration const& timeout)
205
+            {
206
+                const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(timeout));
207
+                // The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
208
+                return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
209
+            }
210
+
211
+            bool timed_lock(boost::xtime const& timeout)
212
+            {
213
+                return timed_lock(boost::system_time(timeout));
214
+            }
215
+#endif
216
+#ifdef BOOST_THREAD_USES_CHRONO
217
+            template <class Rep, class Period>
218
+            bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
219
+            {
220
+                const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
221
+                typedef typename chrono::duration<Rep, Period> Duration;
222
+                typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
223
+                // The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
224
+                return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
225
+            }
226
+            template <class Duration>
227
+            bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
228
+            {
229
+                typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
230
+                // The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
231
+                return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
232
+            }
233
+            template <class Clock, class Duration>
234
+            bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
235
+            {
236
+                typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
237
+                return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
238
+            }
239
+#endif
240
+
241
+            void unlock()
242
+            {
243
+                // Clear the lock flag using atomic addition (works since long is always 32 bits on Windows)
244
+                long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
245
+                // If someone is waiting to take the lock, set the event set flag and, if
246
+                // the event set flag hadn't already been set, send an event.
247
+                if(!(old_count&event_set_flag_value) && (old_count>lock_flag_value))
248
+                {
249
+                    if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
250
+                    {
251
+                        winapi::SetEvent(get_event());
252
+                    }
253
+                }
254
+            }
255
+
256
+        private:
257
+            // Create an event in a thread-safe way
258
+            // The first thread to create the event wins and all other thread will use that event
259
+            void* get_event()
260
+            {
261
+                void* current_event=::boost::detail::interlocked_read_acquire(&event);
262
+
263
+                if(!current_event)
264
+                {
265
+                    void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
266
+#ifdef BOOST_MSVC
267
+#pragma warning(push)
268
+#pragma warning(disable:4311)
269
+#pragma warning(disable:4312)
270
+#endif
271
+                    void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
272
+#ifdef BOOST_MSVC
273
+#pragma warning(pop)
274
+#endif
275
+                    if(old_event!=0)
276
+                    {
277
+                        winapi::CloseHandle(new_event);
278
+                        return old_event;
279
+                    }
280
+                    else
281
+                    {
282
+                        return new_event;
283
+                    }
284
+                }
285
+                return current_event;
286
+            }
287
+
288
+        };
289
+
290
+    }
291
+}
292
+
293
+#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
294
+
295
+#include <boost/config/abi_suffix.hpp>
296
+
297
+#endif
0 298
new file mode 100755
... ...
@@ -0,0 +1,725 @@
1
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
2
+#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
3
+// Distributed under the Boost Software License, Version 1.0. (See
4
+// accompanying file LICENSE_1_0.txt or copy at
5
+// http://www.boost.org/LICENSE_1_0.txt)
6
+// (C) Copyright 2007-8 Anthony Williams
7
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
8
+
9
+#include <boost/thread/win32/thread_primitives.hpp>
10
+#include <boost/thread/win32/thread_data.hpp>
11
+#include <boost/thread/win32/thread_data.hpp>
12
+#include <boost/thread/win32/interlocked_read.hpp>
13
+#include <boost/thread/cv_status.hpp>
14
+#if defined BOOST_THREAD_USES_DATETIME
15
+#include <boost/thread/xtime.hpp>
16
+#endif
17
+#include <boost/thread/mutex.hpp>
18
+#include <boost/thread/thread_time.hpp>
19
+#include <boost/thread/lock_guard.hpp>
20
+#include <boost/thread/lock_types.hpp>
21
+#include <boost/thread/detail/platform_time.hpp>
22
+
23
+#include <boost/assert.hpp>
24
+#include <boost/intrusive_ptr.hpp>
25
+
26
+#ifdef BOOST_THREAD_USES_CHRONO
27
+#include <boost/chrono/system_clocks.hpp>
28
+#include <boost/chrono/ceil.hpp>
29
+#endif
30
+
31
+#include <limits.h>
32
+#include <algorithm>
33
+#include <vector>
34
+
35
+#include <boost/config/abi_prefix.hpp>
36
+
37
+namespace boost
38
+{
39
+    namespace detail
40
+    {
41
+        class basic_cv_list_entry;
42
+        void intrusive_ptr_add_ref(basic_cv_list_entry * p);
43
+        void intrusive_ptr_release(basic_cv_list_entry * p);
44
+
45
+        class basic_cv_list_entry
46
+        {
47
+        private:
48
+            detail::win32::handle_manager semaphore;
49
+            detail::win32::handle_manager wake_sem;
50
+            long waiters;
51
+            bool notified;
52
+            long references;
53
+
54
+        public:
55
+            BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry)
56
+            explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
57
+                semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
58
+                wake_sem(wake_sem_.duplicate()),
59
+                waiters(1),notified(false),references(0)
60
+            {}
61
+
62
+            static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
63
+            {
64
+                return !detail::interlocked_read_acquire(&entry->waiters);
65
+            }
66
+
67
+            void add_waiter()
68
+            {
69
+                BOOST_INTERLOCKED_INCREMENT(&waiters);
70
+            }
71
+
72
+            void remove_waiter()
73
+            {
74
+                BOOST_INTERLOCKED_DECREMENT(&waiters);
75
+            }
76
+
77
+            void release(unsigned count_to_release)
78
+            {
79
+                notified=true;
80
+                winapi::ReleaseSemaphore(semaphore,count_to_release,0);
81
+            }
82
+
83
+            void release_waiters()
84
+            {
85
+                release(detail::interlocked_read_acquire(&waiters));
86
+            }
87
+
88
+            bool is_notified() const
89
+            {
90
+                return notified;
91
+            }
92
+
93
+            bool interruptible_wait(detail::internal_platform_timepoint const &timeout)
94
+            {
95
+                return this_thread::interruptible_wait(semaphore, timeout);
96
+            }
97
+
98
+            bool woken()
99
+            {
100
+                unsigned long const woken_result=winapi::WaitForSingleObjectEx(wake_sem,0,0);
101
+                BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
102
+                return woken_result==0;
103
+            }
104
+
105
+            friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
106
+            friend void intrusive_ptr_release(basic_cv_list_entry * p);
107
+        };
108
+
109
+        inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
110
+        {
111
+            BOOST_INTERLOCKED_INCREMENT(&p->references);
112
+        }
113
+
114
+        inline void intrusive_ptr_release(basic_cv_list_entry * p)
115
+        {
116
+            if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
117
+            {
118
+                delete p;
119
+            }
120
+        }
121
+
122
+        class basic_condition_variable
123
+        {
124
+            boost::mutex internal_mutex;
125
+            long total_count;
126
+            unsigned active_generation_count;
127
+
128
+            typedef basic_cv_list_entry list_entry;
129
+
130
+            typedef boost::intrusive_ptr<list_entry> entry_ptr;
131
+            typedef std::vector<entry_ptr> generation_list;
132
+
133
+            generation_list generations;
134
+            detail::win32::handle_manager wake_sem;
135
+
136
+            void wake_waiters(long count_to_wake)
137
+            {
138
+                detail::interlocked_write_release(&total_count,total_count-count_to_wake);
139
+                winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
140
+            }
141
+
142
+            template<typename lock_type>
143
+            struct relocker
144
+            {
145
+                BOOST_THREAD_NO_COPYABLE(relocker)
146
+                lock_type& _lock;
147
+                bool _unlocked;
148
+
149
+                relocker(lock_type& lock_):
150
+                    _lock(lock_), _unlocked(false)
151
+                {}
152
+                void unlock()
153
+                {
154
+                  if ( ! _unlocked )
155
+                  {
156
+                    _lock.unlock();
157
+                    _unlocked=true;
158
+                  }
159
+                }
160
+                void lock()
161
+                {
162
+                  if ( _unlocked )
163
+                  {
164
+                    _lock.lock();
165
+                    _unlocked=false;
166
+                  }
167
+                }
168
+                ~relocker() BOOST_NOEXCEPT_IF(false)
169
+                {
170
+                  lock();
171
+                }
172
+            };
173
+
174
+
175
+            entry_ptr get_wait_entry()
176
+            {
177
+                boost::lock_guard<boost::mutex> lk(internal_mutex);
178
+                if(!wake_sem)
179
+                {
180
+                    wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
181
+                    BOOST_ASSERT(wake_sem);
182
+                }
183
+
184
+                detail::interlocked_write_release(&total_count,total_count+1);
185
+                if(generations.empty() || generations.back()->is_notified())
186
+                {
187
+                    entry_ptr new_entry(new list_entry(wake_sem));
188
+                    generations.push_back(new_entry);
189
+                    return new_entry;
190
+                }
191
+                else
192
+                {
193
+                    generations.back()->add_waiter();
194
+                    return generations.back();
195
+                }
196
+            }
197
+
198
+            struct entry_manager
199
+            {
200
+                entry_ptr entry;
201
+                boost::mutex& internal_mutex;
202
+
203
+
204
+                BOOST_THREAD_NO_COPYABLE(entry_manager)
205
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
206
+                entry_manager(entry_ptr&& entry_, boost::mutex& mutex_):
207
+                    entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_)
208
+                {}
209
+#else
210
+                entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
211
+                    entry(entry_), internal_mutex(mutex_)
212
+                {}
213
+#endif
214
+
215
+                void remove_waiter_and_reset()
216
+                {
217
+                  if (entry) {
218
+                    boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
219
+                    entry->remove_waiter();
220
+                    entry.reset();
221
+                  }
222
+                }
223
+                ~entry_manager() BOOST_NOEXCEPT_IF(false)
224
+                {
225
+                  remove_waiter_and_reset();
226
+                }
227
+
228
+                list_entry* operator->()
229
+                {
230
+                    return entry.get();
231
+                }
232
+            };
233
+
234
+        protected:
235
+            basic_condition_variable(const basic_condition_variable& other);
236
+            basic_condition_variable& operator=(const basic_condition_variable& other);
237
+
238
+        public:
239
+            basic_condition_variable():
240
+                total_count(0),active_generation_count(0),wake_sem(0)
241
+            {}
242
+
243
+            ~basic_condition_variable()
244
+            {}
245
+
246
+            // When this function returns true:
247
+            // * A notification (or sometimes a spurious OS signal) has been received
248
+            // * Do not assume that the timeout has not been reached
249
+            // * Do not assume that the predicate has been changed
250
+            //
251
+            // When this function returns false:
252
+            // * The timeout has been reached
253
+            // * Do not assume that a notification has not been received
254
+            // * Do not assume that the predicate has not been changed
255
+            template<typename lock_type>
256
+            bool do_wait_until(lock_type& lock, detail::internal_platform_timepoint const &timeout)
257
+            {
258
+              relocker<lock_type> locker(lock);
259
+              entry_manager entry(get_wait_entry(), internal_mutex);
260
+              locker.unlock();
261
+
262
+              bool woken=false;
263
+              while(!woken)
264
+              {
265
+                  if(!entry->interruptible_wait(timeout))
266
+                  {
267
+                      return false;
268
+                  }
269
+
270
+                  woken=entry->woken();
271
+              }
272
+              // do it here to avoid throwing on the destructor
273
+              entry.remove_waiter_and_reset();
274
+              locker.lock();
275
+              return true;
276
+            }
277
+
278
+            void notify_one() BOOST_NOEXCEPT
279
+            {
280
+                if(detail::interlocked_read_acquire(&total_count))
281
+                {
282
+                    boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
283
+                    if(!total_count)
284
+                    {
285
+                        return;
286
+                    }
287
+                    wake_waiters(1);
288
+
289
+                    for(generation_list::iterator it=generations.begin(),
290
+                            end=generations.end();
291
+                        it!=end;++it)
292
+                    {
293
+                        (*it)->release(1);
294
+                    }
295
+                    generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
296
+                }
297
+            }
298
+
299
+            void notify_all() BOOST_NOEXCEPT
300
+            {
301
+                if(detail::interlocked_read_acquire(&total_count))
302
+                {
303
+                    boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
304
+                    if(!total_count)
305
+                    {
306
+                        return;
307
+                    }
308
+                    wake_waiters(total_count);
309
+                    for(generation_list::iterator it=generations.begin(),
310
+                            end=generations.end();
311
+                        it!=end;++it)
312
+                    {
313
+                        (*it)->release_waiters();
314
+                    }
315
+                    generations.clear();
316
+                    wake_sem=detail::win32::handle(0);
317
+                }
318
+            }
319
+
320
+        };
321
+    }
322
+
323
+    class condition_variable:
324
+        private detail::basic_condition_variable
325
+    {
326
+    public:
327
+        BOOST_THREAD_NO_COPYABLE(condition_variable)
328
+        condition_variable()
329
+        {}
330
+
331
+        using detail::basic_condition_variable::do_wait_until;
332
+        using detail::basic_condition_variable::notify_one;
333
+        using detail::basic_condition_variable::notify_all;
334
+
335
+        void wait(unique_lock<mutex>& m)
336
+        {
337
+            do_wait_until(m, detail::internal_platform_timepoint::getMax());
338
+        }
339
+
340
+        template<typename predicate_type>
341
+        void wait(unique_lock<mutex>& m,predicate_type pred)
342
+        {
343
+            while (!pred())
344
+            {
345
+                wait(m);
346
+            }
347
+        }
348
+
349
+#if defined BOOST_THREAD_USES_DATETIME
350
+        bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
351
+        {
352
+            // The system time may jump while this function is waiting. To compensate for this and time
353
+            // out near the correct time, we could call do_wait_until() in a loop with a short timeout
354
+            // and recheck the time remaining each time through the loop. However, because we can't
355
+            // check the predicate each time do_wait_until() completes, this introduces the possibility
356
+            // of not exiting the function when a notification occurs, since do_wait_until() may report
357
+            // that it timed out even though a notification was received. The best this function can do
358
+            // is report correctly whether or not it reached the timeout time.
359
+            const detail::real_platform_timepoint ts(abs_time);
360
+            const detail::platform_duration d(ts - detail::real_platform_clock::now());
361
+            do_wait_until(m, detail::internal_platform_clock::now() + d);
362
+            return ts > detail::real_platform_clock::now();
363
+        }
364
+        bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
365
+        {
366
+            return timed_wait(m, system_time(abs_time));
367
+        }
368
+        template<typename duration_type>
369
+        bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
370
+        {
371
+            if (wait_duration.is_pos_infinity())
372
+            {
373
+                wait(m);
374
+                return true;
375
+            }
376
+            if (wait_duration.is_special())
377
+            {
378
+                return true;
379
+            }
380
+            const detail::platform_duration d(wait_duration);
381
+            return do_wait_until(m, detail::internal_platform_clock::now() + d);
382
+        }
383
+
384
+        template<typename predicate_type>
385
+        bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
386
+        {
387
+            // The system time may jump while this function is waiting. To compensate for this
388
+            // and time out near the correct time, we call do_wait_until() in a loop with a
389
+            // short timeout and recheck the time remaining each time through the loop.
390
+            const detail::real_platform_timepoint ts(abs_time);
391
+            while (!pred())
392
+            {
393
+                detail::platform_duration d(ts - detail::real_platform_clock::now());
394
+                if (d <= detail::platform_duration::zero()) break; // timeout occurred
395
+                d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
396
+                do_wait_until(m, detail::internal_platform_clock::now() + d);
397
+            }
398
+            return pred();
399
+        }
400
+        template<typename predicate_type>
401
+        bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
402
+        {
403
+            return timed_wait(m, system_time(abs_time), pred);
404
+        }
405
+        template<typename duration_type,typename predicate_type>
406
+        bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
407
+        {
408
+            if (wait_duration.is_pos_infinity())
409
+            {
410
+                while (!pred())
411
+                {
412
+                    wait(m);
413
+                }
414
+                return true;
415
+            }
416
+            if (wait_duration.is_special())
417
+            {
418
+                return pred();
419
+            }
420
+            const detail::platform_duration d(wait_duration);
421
+            const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
422
+            while (!pred())
423
+            {
424
+                if (!do_wait_until(m, ts)) break; // timeout occurred
425
+            }
426
+            return pred();
427
+        }
428
+#endif
429
+#ifdef BOOST_THREAD_USES_CHRONO
430
+        template <class Duration>
431
+        cv_status
432
+        wait_until(
433
+                unique_lock<mutex>& lock,
434
+                const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
435
+        {
436
+            const detail::internal_platform_timepoint ts(t);
437
+            if (do_wait_until(lock, ts)) return cv_status::no_timeout;
438
+            else return cv_status::timeout;
439
+        }
440
+
441
+        template <class Clock, class Duration>
442
+        cv_status
443
+        wait_until(
444
+                unique_lock<mutex>& lock,
445
+                const chrono::time_point<Clock, Duration>& t)
446
+        {
447
+            // The system time may jump while this function is waiting. To compensate for this and time
448
+            // out near the correct time, we could call do_wait_until() in a loop with a short timeout
449
+            // and recheck the time remaining each time through the loop. However, because we can't
450
+            // check the predicate each time do_wait_until() completes, this introduces the possibility
451
+            // of not exiting the function when a notification occurs, since do_wait_until() may report
452
+            // that it timed out even though a notification was received. The best this function can do
453
+            // is report correctly whether or not it reached the timeout time.
454
+            typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
455
+            common_duration d(t - Clock::now());
456
+            do_wait_until(lock, detail::internal_chrono_clock::now() + d);
457
+            if (t > Clock::now()) return cv_status::no_timeout;
458
+            else return cv_status::timeout;
459
+        }
460
+
461
+        template <class Rep, class Period>
462
+        cv_status
463
+        wait_for(
464
+                unique_lock<mutex>& lock,
465
+                const chrono::duration<Rep, Period>& d)
466
+        {
467
+            return wait_until(lock, chrono::steady_clock::now() + d);
468
+        }
469
+
470
+        template <class Duration, class Predicate>
471
+        bool
472
+        wait_until(
473
+                unique_lock<mutex>& lock,
474
+                const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
475
+                Predicate pred)
476
+        {
477
+            const detail::internal_platform_timepoint ts(t);
478
+            while (!pred())
479
+            {
480
+                if (!do_wait_until(lock, ts)) break; // timeout occurred
481
+            }
482
+            return pred();
483
+        }
484
+
485
+        template <class Clock, class Duration, class Predicate>
486
+        bool
487
+        wait_until(
488
+                unique_lock<mutex>& lock,
489
+                const chrono::time_point<Clock, Duration>& t,
490
+                Predicate pred)
491
+        {
492
+            // The system time may jump while this function is waiting. To compensate for this
493
+            // and time out near the correct time, we call do_wait_until() in a loop with a
494
+            // short timeout and recheck the time remaining each time through the loop.
495
+            typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
496
+            while (!pred())
497
+            {
498
+                common_duration d(t - Clock::now());
499
+                if (d <= common_duration::zero()) break; // timeout occurred
500
+                d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
501
+                do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
502
+            }
503
+            return pred();
504
+        }
505
+
506
+        template <class Rep, class Period, class Predicate>
507
+        bool
508
+        wait_for(
509
+                unique_lock<mutex>& lock,
510
+                const chrono::duration<Rep, Period>& d,
511
+                Predicate pred)
512
+        {
513
+            return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
514
+        }
515
+#endif
516
+    };
517
+
518
+    class condition_variable_any:
519
+        private detail::basic_condition_variable
520
+    {
521
+    public:
522
+        BOOST_THREAD_NO_COPYABLE(condition_variable_any)
523
+        condition_variable_any()
524
+        {}
525
+
526
+        using detail::basic_condition_variable::do_wait_until;
527
+        using detail::basic_condition_variable::notify_one;
528
+        using detail::basic_condition_variable::notify_all;
529
+
530
+        template<typename lock_type>
531
+        void wait(lock_type& m)
532
+        {
533
+            do_wait_until(m, detail::internal_platform_timepoint::getMax());
534
+        }
535
+
536
+        template<typename lock_type,typename predicate_type>
537
+        void wait(lock_type& m,predicate_type pred)
538
+        {
539
+            while (!pred())
540
+            {
541
+                wait(m);
542
+            }
543
+        }
544
+
545
+#if defined BOOST_THREAD_USES_DATETIME
546
+        template<typename lock_type>
547
+        bool timed_wait(lock_type& m,boost::system_time const& abs_time)
548
+        {
549
+            // The system time may jump while this function is waiting. To compensate for this and time
550
+            // out near the correct time, we could call do_wait_until() in a loop with a short timeout
551
+            // and recheck the time remaining each time through the loop. However, because we can't
552
+            // check the predicate each time do_wait_until() completes, this introduces the possibility
553
+            // of not exiting the function when a notification occurs, since do_wait_until() may report
554
+            // that it timed out even though a notification was received. The best this function can do
555
+            // is report correctly whether or not it reached the timeout time.
556
+            const detail::real_platform_timepoint ts(abs_time);
557
+            const detail::platform_duration d(ts - detail::real_platform_clock::now());
558
+            do_wait_until(m, detail::internal_platform_clock::now() + d);
559
+            return ts > detail::real_platform_clock::now();
560
+        }
561
+
562
+        template<typename lock_type>
563
+        bool timed_wait(lock_type& m,boost::xtime const& abs_time)
564
+        {
565
+            return timed_wait(m, system_time(abs_time));
566
+        }
567
+
568
+        template<typename lock_type,typename duration_type>
569
+        bool timed_wait(lock_type& m,duration_type const& wait_duration)
570
+        {
571
+            if (wait_duration.is_pos_infinity())
572
+            {
573
+                wait(m);
574
+                return true;
575
+            }
576
+            if (wait_duration.is_special())
577
+            {
578
+                return true;
579
+            }
580
+            const detail::platform_duration d(wait_duration);
581
+            return do_wait_until(m, detail::internal_platform_clock::now() + d);
582
+        }
583
+
584
+        template<typename lock_type,typename predicate_type>
585
+        bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
586
+        {
587
+            // The system time may jump while this function is waiting. To compensate for this
588
+            // and time out near the correct time, we call do_wait_until() in a loop with a
589
+            // short timeout and recheck the time remaining each time through the loop.
590
+            const detail::real_platform_timepoint ts(abs_time);
591
+            while (!pred())
592
+            {
593
+                detail::platform_duration d(ts - detail::real_platform_clock::now());
594
+                if (d <= detail::platform_duration::zero()) break; // timeout occurred
595
+                d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
596
+                do_wait_until(m, detail::internal_platform_clock::now() + d);
597
+            }
598
+            return pred();
599
+        }
600
+
601
+        template<typename lock_type,typename predicate_type>
602
+        bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
603
+        {
604
+            return timed_wait(m, system_time(abs_time), pred);
605
+        }
606
+
607
+        template<typename lock_type,typename duration_type,typename predicate_type>
608
+        bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
609
+        {
610
+            if (wait_duration.is_pos_infinity())
611
+            {
612
+                while (!pred())
613
+                {
614
+                    wait(m);
615
+                }
616
+                return true;
617
+            }
618
+            if (wait_duration.is_special())
619
+            {
620
+                return pred();
621
+            }
622
+            const detail::platform_duration d(wait_duration);
623
+            const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
624
+            while (!pred())
625
+            {
626
+                if (!do_wait_until(m, ts)) break; // timeout occurred
627
+            }
628
+            return pred();
629
+        }
630
+#endif
631
+#ifdef BOOST_THREAD_USES_CHRONO
632
+        template <class lock_type,class Duration>
633
+        cv_status
634
+        wait_until(
635
+                lock_type& lock,
636
+                const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
637
+        {
638
+            const detail::internal_platform_timepoint ts(t);
639
+            if (do_wait_until(lock, ts)) return cv_status::no_timeout;
640
+            else return cv_status::timeout;
641
+        }
642
+
643
+        template <class lock_type, class Clock, class Duration>
644
+        cv_status
645
+        wait_until(
646
+                lock_type& lock,
647
+                const chrono::time_point<Clock, Duration>& t)
648
+        {
649
+            // The system time may jump while this function is waiting. To compensate for this and time
650
+            // out near the correct time, we could call do_wait_until() in a loop with a short timeout
651
+            // and recheck the time remaining each time through the loop. However, because we can't
652
+            // check the predicate each time do_wait_until() completes, this introduces the possibility
653
+            // of not exiting the function when a notification occurs, since do_wait_until() may report
654
+            // that it timed out even though a notification was received. The best this function can do
655
+            // is report correctly whether or not it reached the timeout time.
656
+            typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
657
+            common_duration d(t - Clock::now());
658
+            do_wait_until(lock, detail::internal_chrono_clock::now() + d);
659
+            if (t > Clock::now()) return cv_status::no_timeout;
660
+            else return cv_status::timeout;
661
+        }
662
+
663
+        template <class lock_type,  class Rep, class Period>
664
+        cv_status
665
+        wait_for(
666
+                lock_type& lock,
667
+                const chrono::duration<Rep, Period>& d)
668
+        {
669
+            return wait_until(lock, chrono::steady_clock::now() + d);
670
+        }
671
+
672
+        template <class lock_type, class Clock, class Duration, class Predicate>
673
+        bool
674
+        wait_until(
675
+                lock_type& lock,
676
+                const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
677
+                Predicate pred)
678
+        {
679
+            const detail::internal_platform_timepoint ts(t);
680
+            while (!pred())
681
+            {
682
+                if (!do_wait_until(lock, ts)) break; // timeout occurred
683
+            }
684
+            return pred();
685
+        }
686
+
687
+        template <class lock_type, class Clock, class Duration, class Predicate>
688
+        bool
689
+        wait_until(
690
+                lock_type& lock,
691
+                const chrono::time_point<Clock, Duration>& t,
692
+                Predicate pred)
693
+        {
694
+            // The system time may jump while this function is waiting. To compensate for this
695
+            // and time out near the correct time, we call do_wait_until() in a loop with a
696
+            // short timeout and recheck the time remaining each time through the loop.
697
+            typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
698
+            while (!pred())
699
+            {
700
+                common_duration d(t - Clock::now());
701
+                if (d <= common_duration::zero()) break; // timeout occurred
702
+                d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
703
+                do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
704
+            }
705
+            return pred();
706
+        }
707
+
708
+        template <class lock_type, class Rep, class Period, class Predicate>
709
+        bool
710
+        wait_for(
711
+                lock_type& lock,
712
+                const chrono::duration<Rep, Period>& d,
713
+                Predicate pred)
714
+        {
715
+            return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
716
+        }
717
+#endif
718
+    };
719
+
720
+        BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
721
+}
722
+
723
+#include <boost/config/abi_suffix.hpp>
724
+
725
+#endif
0 726
new file mode 100755
... ...
@@ -0,0 +1,216 @@
1
+#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
2
+#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
3
+
4
+//  interlocked_read_win32.hpp
5
+//
6
+//  (C) Copyright 2005-8 Anthony Williams
7
+//  (C) Copyright 2012 Vicente J. Botet Escriba
8
+//  (C) Copyright 2017 Andrey Semashev
9
+//
10
+//  Distributed under the Boost Software License, Version 1.0. (See
11
+//  accompanying file LICENSE_1_0.txt or copy at
12
+//  http://www.boost.org/LICENSE_1_0.txt)
13
+
14
+#include <boost/detail/interlocked.hpp>
15
+#include <boost/thread/detail/config.hpp>
16
+
17
+#include <boost/config/abi_prefix.hpp>
18
+
19
+// Define compiler barriers
20
+#if defined(__INTEL_COMPILER)
21
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
22
+#elif defined(__clang__)
23
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __atomic_signal_fence(__ATOMIC_SEQ_CST)
24
+#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
25
+extern "C" void _ReadWriteBarrier(void);
26
+#pragma intrinsic(_ReadWriteBarrier)
27
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
28
+#endif
29
+
30
+#ifndef BOOST_THREAD_DETAIL_COMPILER_BARRIER
31
+#define BOOST_THREAD_DETAIL_COMPILER_BARRIER()
32
+#endif
33
+
34
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
35
+
36
+// Since VS2005 and until VS2012 volatile reads always acquire and volatile writes are always release.
37
+// But VS2012 adds a compiler switch that can change behavior to the standard. On x86 though
38
+// the compiler generates a single instruction for the load/store, which is enough synchronization
39
+// as far as uarch is concerned. To prevent compiler reordering code around the load/store we add
40
+// compiler barriers.
41
+
42
+namespace boost
43
+{
44
+    namespace detail
45
+    {
46
+        inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
47
+        {
48
+            long const res=*x;
49
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
50
+            return res;
51
+        }
52
+        inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
53
+        {
54
+            void* const res=*x;
55
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
56
+            return res;
57
+        }
58
+
59
+        inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
60
+        {
61
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
62
+            *x=value;
63
+        }
64
+        inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
65
+        {
66
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
67
+            *x=value;
68
+        }
69
+    }
70
+}
71
+
72
+#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
73
+
74
+#include <intrin.h>
75
+
76
+namespace boost
77
+{
78
+    namespace detail
79
+    {
80
+        inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
81
+        {
82
+            long const res=__iso_volatile_load32((const volatile __int32*)x);
83
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
84
+            __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
85
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
86
+            return res;
87
+        }
88
+        inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
89
+        {
90
+            void* const res=
91
+#if defined(_M_ARM64)
92
+                (void*)__iso_volatile_load64((const volatile __int64*)x);
93
+#else
94
+                (void*)__iso_volatile_load32((const volatile __int32*)x);
95
+#endif
96
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
97
+            __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
98
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
99
+            return res;
100
+        }
101
+
102
+        inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
103
+        {
104
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
105
+            __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
106
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
107
+            __iso_volatile_store32((volatile __int32*)x, (__int32)value);
108
+        }
109
+        inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
110
+        {
111
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
112
+            __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
113
+            BOOST_THREAD_DETAIL_COMPILER_BARRIER();
114
+#if defined(_M_ARM64)
115
+            __iso_volatile_store64((volatile __int64*)x, (__int64)value);
116
+#else
117
+            __iso_volatile_store32((volatile __int32*)x, (__int32)value);
118
+#endif
119
+        }
120
+    }
121
+}
122
+
123
+#elif defined(__GNUC__) && (((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) || (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 302))
124
+
125
+namespace boost
126
+{
127
+    namespace detail
128
+    {
129
+        inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
130
+        {
131
+            return __atomic_load_n((long*)x, __ATOMIC_ACQUIRE);
132
+        }
133
+        inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
134
+        {
135
+            return __atomic_load_n((void**)x, __ATOMIC_ACQUIRE);
136
+        }
137
+
138
+        inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
139
+        {
140
+            __atomic_store_n((long*)x, value, __ATOMIC_RELEASE);
141
+        }
142
+        inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
143
+        {
144
+            __atomic_store_n((void**)x, value, __ATOMIC_RELEASE);
145
+        }
146
+    }
147
+}
148
+
149
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
150
+
151
+namespace boost
152
+{
153
+    namespace detail
154
+    {
155
+        inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
156
+        {
157
+            long res;
158
+            __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
159
+            return res;
160
+        }
161
+        inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
162
+        {
163
+            void* res;
164
+#if defined(__x86_64__)
165
+            __asm__ __volatile__ ("movq %1, %0" : "=r" (res) : "m" (*x) : "memory");
166
+#else
167
+            __asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
168
+#endif
169
+            return res;
170
+        }
171
+
172
+        inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
173
+        {
174
+            __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
175
+        }
176
+        inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
177
+        {
178
+#if defined(__x86_64__)
179
+            __asm__ __volatile__ ("movq %1, %0" : "=m" (*x) : "r" (value) : "memory");
180
+#else
181
+            __asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
182
+#endif
183
+        }
184
+    }
185
+}
186
+
187
+#else
188
+
189
+namespace boost
190
+{
191
+    namespace detail
192
+    {
193
+        inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
194
+        {
195
+            return BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)x,0,0);
196
+        }
197
+        inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
198
+        {
199
+            return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)x,0,0);
200
+        }
201
+        inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
202
+        {
203
+            BOOST_INTERLOCKED_EXCHANGE((long*)x,value);
204
+        }
205
+        inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
206
+        {
207
+            BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)x,value);
208
+        }
209
+    }
210
+}
211
+
212
+#endif
213
+
214
+#include <boost/config/abi_suffix.hpp>
215
+
216
+#endif
0 217
new file mode 100755
... ...
@@ -0,0 +1,40 @@
1
+#ifndef BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
2
+#define BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
3
+// Distributed under the Boost Software License, Version 1.0. (See
4
+// accompanying file LICENSE_1_0.txt or copy at
5
+// http://www.boost.org/LICENSE_1_0.txt)
6
+// (C) Copyright 2008 Anthony Williams
7
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
8
+
9
+
10
+// check if we use MFC
11
+#ifdef _AFXDLL
12
+# if defined(_AFXEXT)
13
+
14
+// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain
15
+extern "C"
16
+inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
17
+{
18
+  if (dwReason == DLL_PROCESS_ATTACH)
19
+  {
20
+    // save critical data pointers before running the constructors
21
+    AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
22
+    pModuleState->m_pClassInit = pModuleState->m_classList;
23
+    pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
24
+    pModuleState->m_classList.m_pHead = NULL;
25
+    pModuleState->m_factoryList.m_pHead = NULL;
26
+  }
27
+  return TRUE; // ok
28
+}
29
+
30
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &ExtRawDllMain;
31
+
32
+# elif defined(_USRDLL)
33
+
34
+extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
35
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
36
+
37
+# endif
38
+#endif
39
+
40
+#endif
0 41
new file mode 100755
... ...
@@ -0,0 +1,72 @@
1
+#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
2
+#define BOOST_THREAD_WIN32_MUTEX_HPP
3
+// (C) Copyright 2005-7 Anthony Williams
4
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
5
+// Distributed under the Boost Software License, Version 1.0. (See
6
+// accompanying file LICENSE_1_0.txt or copy at
7
+// http://www.boost.org/LICENSE_1_0.txt)
8
+
9
+#include <boost/thread/win32/basic_timed_mutex.hpp>
10
+#include <boost/thread/exceptions.hpp>
11
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
12
+#include <boost/thread/lock_types.hpp>
13
+#endif
14
+#include <boost/thread/detail/delete.hpp>
15
+
16
+#include <boost/config/abi_prefix.hpp>
17
+
18
+namespace boost
19
+{
20
+    namespace detail
21
+    {
22
+        typedef ::boost::detail::basic_timed_mutex underlying_mutex;
23
+    }
24
+
25
+    class mutex:
26
+        public ::boost::detail::underlying_mutex
27
+    {
28
+    public:
29
+        BOOST_THREAD_NO_COPYABLE(mutex)
30
+        mutex()
31
+        {
32
+            initialize();
33
+        }
34
+        ~mutex()
35
+        {
36
+            destroy();
37
+        }
38
+
39
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
40
+        typedef unique_lock<mutex> scoped_lock;
41
+        typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
42
+#endif
43
+    };
44
+
45
+    typedef mutex try_mutex;
46
+
47
+    class timed_mutex:
48
+        public ::boost::detail::basic_timed_mutex
49
+    {
50
+    public:
51
+        BOOST_THREAD_NO_COPYABLE(timed_mutex)
52
+        timed_mutex()
53
+        {
54
+            initialize();
55
+        }
56
+
57
+        ~timed_mutex()
58
+        {
59
+            destroy();
60
+        }
61
+
62
+#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
63
+        typedef unique_lock<timed_mutex> scoped_timed_lock;
64
+        typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
65
+        typedef scoped_timed_lock scoped_lock;
66
+#endif
67
+    };
68
+}
69
+
70
+#include <boost/config/abi_suffix.hpp>
71
+
72
+#endif
0 73
new file mode 100755
... ...
@@ -0,0 +1,1087 @@
1
+#ifndef BOOST_THREAD_WIN32_ONCE_HPP
2
+#define BOOST_THREAD_WIN32_ONCE_HPP
3
+
4
+//  once.hpp
5
+//
6
+//  (C) Copyright 2005-7 Anthony Williams
7
+//  (C) Copyright 2005 John Maddock
8
+//  (C) Copyright 2011-2013 Vicente J. Botet Escriba
9
+//
10
+//  Distributed under the Boost Software License, Version 1.0. (See
11
+//  accompanying file LICENSE_1_0.txt or copy at
12
+//  http://www.boost.org/LICENSE_1_0.txt)
13
+
14
+#include <cstring>
15
+#include <cstddef>
16
+#include <boost/assert.hpp>
17
+#include <boost/static_assert.hpp>
18
+#include <boost/detail/interlocked.hpp>
19
+#include <boost/thread/win32/thread_primitives.hpp>
20
+#include <boost/thread/win32/interlocked_read.hpp>
21
+#include <boost/core/no_exceptions_support.hpp>
22
+#include <boost/thread/detail/move.hpp>
23
+#include <boost/thread/detail/invoke.hpp>
24
+
25
+#include <boost/bind/bind.hpp>
26
+
27
+#include <boost/config/abi_prefix.hpp>
28
+
29
+#ifdef BOOST_NO_STDC_NAMESPACE
30
+namespace std
31
+{
32
+    using ::memcpy;
33
+    using ::ptrdiff_t;
34
+}
35
+#endif
36
+
37
+namespace boost
38
+{
39
+  struct once_flag;
40
+  namespace detail
41
+  {
42
+  struct once_context;
43
+
44
+  inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
45
+  inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
46
+  inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
47
+  }
48
+
49
+#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
50
+
51
+  struct once_flag
52
+  {
53
+      BOOST_THREAD_NO_COPYABLE(once_flag)
54
+      BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
55
+        : status(0), count(0)
56
+      {}
57
+      long status;
58
+      long count;
59
+  private:
60
+      friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
61
+      friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
62
+      friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
63
+  };
64
+
65
+#define BOOST_ONCE_INIT once_flag()
66
+#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
67
+
68
+    struct once_flag
69
+    {
70
+        long status;
71
+        long count;
72
+    };
73
+
74
+#define BOOST_ONCE_INIT {0,0}
75
+#endif  // BOOST_THREAD_PROVIDES_ONCE_CXX11
76
+
77
+#if defined BOOST_THREAD_PROVIDES_INVOKE
78
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
79
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
80
+#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
81
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
82
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
83
+#else
84
+#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
85
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
86
+#endif
87
+
88
+    namespace detail
89
+    {
90
+#ifdef BOOST_NO_ANSI_APIS
91
+        typedef wchar_t once_char_type;
92
+#else
93
+        typedef char once_char_type;
94
+#endif
95
+        unsigned const once_mutex_name_fixed_length=54;
96
+        unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
97
+            sizeof(void*)*2+sizeof(unsigned long)*2+1;
98
+
99
+        template <class I>
100
+        void int_to_string(I p, once_char_type* buf)
101
+        {
102
+            for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
103
+            {
104
+#ifdef BOOST_NO_ANSI_APIS
105
+                once_char_type const a=L'A';
106
+#else
107
+                once_char_type const a='A';
108
+#endif
109
+                *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
110
+            }
111
+            *buf = 0;
112
+        }
113
+
114
+        inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
115
+        {
116
+#ifdef BOOST_NO_ANSI_APIS
117
+            static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
118
+#else
119
+            static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
120
+#endif
121
+            BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
122
+                                (sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
123
+
124
+            std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
125
+            detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
126
+                                  mutex_name + once_mutex_name_fixed_length);
127
+            detail::int_to_string(winapi::GetCurrentProcessId(),
128
+                                  mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
129
+        }
130
+
131
+        inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
132
+        {
133
+            if(!*mutex_name)
134
+            {
135
+                name_once_mutex(mutex_name,flag_address);
136
+            }
137
+
138
+#ifdef BOOST_NO_ANSI_APIS
139
+            return ::boost::winapi::OpenEventW(
140
+#else
141
+            return ::boost::winapi::OpenEventA(
142
+#endif
143
+                ::boost::detail::win32::synchronize |
144
+                ::boost::detail::win32::event_modify_state,
145
+                false,
146
+                mutex_name);
147
+        }
148
+
149
+        inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
150
+        {
151
+            if(!*mutex_name)
152
+            {
153
+                name_once_mutex(mutex_name,flag_address);
154
+            }
155
+            
156
+            return ::boost::detail::win32::create_event(
157
+                mutex_name, 
158
+                ::boost::detail::win32::manual_reset_event,
159
+                ::boost::detail::win32::event_initially_reset);
160
+        }
161
+
162
+        struct once_context {
163
+          long const function_complete_flag_value;
164
+          long const running_value;
165
+          bool counted;
166
+          detail::win32::handle_manager event_handle;
167
+          detail::once_char_type mutex_name[once_mutex_name_length];
168
+          once_context() :
169
+            function_complete_flag_value(0xc15730e2),
170
+            running_value(0x7f0725e3),
171
+            counted(false)
172
+          {
173
+            mutex_name[0]=0;
174
+          }
175
+        };
176
+        enum once_action {try_, break_, continue_};
177
+
178
+        inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
179
+        {
180
+          long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0);
181
+          if(!status)
182
+          {
183
+            if(!ctx.event_handle)
184
+            {
185
+                ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
186
+            }
187
+            if(ctx.event_handle)
188
+            {
189
+                ::boost::winapi::ResetEvent(ctx.event_handle);
190
+            }
191
+            return true;
192
+          }
193
+          return false;
194
+        }
195
+        inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
196
+        {
197
+          if(!ctx.counted)
198
+          {
199
+              BOOST_INTERLOCKED_INCREMENT(&flag.count);
200
+              ctx.counted=true;
201
+          }
202
+          BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value);
203
+          if(!ctx.event_handle &&
204
+             (::boost::detail::interlocked_read_acquire(&flag.count)>1))
205
+          {
206
+              ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
207
+          }
208
+          if(ctx.event_handle)
209
+          {
210
+              ::boost::winapi::SetEvent(ctx.event_handle);
211
+          }
212
+        }
213
+        inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
214
+        {
215
+          BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
216
+          if(!ctx.event_handle)
217
+          {
218
+              ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
219
+          }
220
+          if(ctx.event_handle)
221
+          {
222
+              ::boost::winapi::SetEvent(ctx.event_handle);
223
+          }
224
+        }
225
+    }
226
+
227
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
228
+//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
229
+    inline void call_once(once_flag& flag, void (*f)())
230
+    {
231
+        // Try for a quick win: if the procedure has already been called
232
+        // just skip through:
233
+        detail::once_context ctx;
234
+        while(::boost::detail::interlocked_read_acquire(&flag.status)
235
+              !=ctx.function_complete_flag_value)
236
+        {
237
+            if(detail::enter_once_region(flag, ctx))
238
+            {
239
+                BOOST_TRY
240
+                {
241
+                  f();
242
+                }
243
+                BOOST_CATCH(...)
244
+                {
245
+                    detail::rollback_once_region(flag, ctx);
246
+                    BOOST_RETHROW
247
+                }
248
+                BOOST_CATCH_END
249
+                detail::commit_once_region(flag, ctx);
250
+                break;
251
+            }
252
+            if(!ctx.counted)
253
+            {
254
+                BOOST_INTERLOCKED_INCREMENT(&flag.count);
255
+                ctx.counted=true;
256
+                long status=::boost::detail::interlocked_read_acquire(&flag.status);
257
+                if(status==ctx.function_complete_flag_value)
258
+                {
259
+                    break;
260
+                }
261
+                if(!ctx.event_handle)
262
+                {
263
+                    ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
264
+                    continue;
265
+                }
266
+            }
267
+            BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
268
+                             ctx.event_handle,::boost::detail::win32::infinite, 0));
269
+        }
270
+    }
271
+//#endif
272
+    template<typename Function>
273
+    inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
274
+    {
275
+        // Try for a quick win: if the procedure has already been called
276
+        // just skip through:
277
+        detail::once_context ctx;
278
+        while(::boost::detail::interlocked_read_acquire(&flag.status)
279
+              !=ctx.function_complete_flag_value)
280
+        {
281
+            if(detail::enter_once_region(flag, ctx))
282
+            {
283
+                BOOST_TRY
284
+                {
285
+                    f();
286
+                }
287
+                BOOST_CATCH(...)
288
+                {
289
+                    detail::rollback_once_region(flag, ctx);
290
+                    BOOST_RETHROW
291
+                }
292
+                BOOST_CATCH_END
293
+                detail::commit_once_region(flag, ctx);
294
+                break;
295
+            }
296
+            if(!ctx.counted)
297
+            {
298
+                BOOST_INTERLOCKED_INCREMENT(&flag.count);
299
+                ctx.counted=true;
300
+                long status=::boost::detail::interlocked_read_acquire(&flag.status);
301
+                if(status==ctx.function_complete_flag_value)
302
+                {
303
+                    break;
304
+                }
305
+                if(!ctx.event_handle)
306
+                {
307
+                    ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
308
+                    continue;
309
+                }
310
+            }
311
+            BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
312
+                             ctx.event_handle,::boost::detail::win32::infinite,0));
313
+        }
314
+    }
315
+    template<typename Function, class A, class ...ArgTypes>
316
+    inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args)
317
+    {
318
+        // Try for a quick win: if the procedure has already been called
319
+        // just skip through:
320
+        detail::once_context ctx;
321
+        while(::boost::detail::interlocked_read_acquire(&flag.status)
322
+              !=ctx.function_complete_flag_value)
323
+        {
324
+            if(detail::enter_once_region(flag, ctx))
325
+            {
326
+                BOOST_TRY
327
+                {
328
+                  BOOST_THREAD_INVOKE_RET_VOID(
329
+                        thread_detail::decay_copy(boost::forward<Function>(f)),
330
+                        thread_detail::decay_copy(boost::forward<A>(a)),
331
+                        thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
332
+                  ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
333
+                }
334
+                BOOST_CATCH(...)
335
+                {
336
+                    detail::rollback_once_region(flag, ctx);
337
+                    BOOST_RETHROW
338
+                }
339
+                BOOST_CATCH_END
340
+                detail::commit_once_region(flag, ctx);
341
+                break;
342
+            }
343
+            if(!ctx.counted)
344
+            {
345
+                BOOST_INTERLOCKED_INCREMENT(&flag.count);
346
+                ctx.counted=true;
347
+                long status=::boost::detail::interlocked_read_acquire(&flag.status);
348
+                if(status==ctx.function_complete_flag_value)
349
+                {
350
+                    break;
351
+                }
352
+                if(!ctx.event_handle)
353
+                {
354
+                    ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
355
+                    continue;
356
+                }
357
+            }
358
+            BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
359
+                             ctx.event_handle,::boost::detail::win32::infinite,0));
360
+        }
361
+    }
362
+#else
363
+#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
364
+    template<typename Function>
365
+    void call_once(once_flag& flag,Function f)
366
+    {
367
+        // Try for a quick win: if the procedure has already been called
368
+        // just skip through:
369
+        detail::once_context ctx;
370
+        while(::boost::detail::interlocked_read_acquire(&flag.status)
371
+              !=ctx.function_complete_flag_value)
372
+        {
373
+            if(detail::enter_once_region(flag, ctx))
374
+            {
375
+                BOOST_TRY
376
+                {
377
+                    f();
378
+                }
379
+                BOOST_CATCH(...)
380
+                {
381
+                    detail::rollback_once_region(flag, ctx);
382
+                    BOOST_RETHROW
383
+                }
384
+                BOOST_CATCH_END
385
+                detail::commit_once_region(flag, ctx);
386
+                break;
387
+            }
388
+            if(!ctx.counted)
389
+            {
390
+                BOOST_INTERLOCKED_INCREMENT(&flag.count);
391
+                ctx.counted=true;
392
+                long status=::boost::detail::interlocked_read_acquire(&flag.status);
393
+                if(status==ctx.function_complete_flag_value)
394
+                {
395
+                    break;
396
+                }
397
+                if(!ctx.event_handle)
398
+                {
399
+                    ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
400
+                    continue;
401
+                }
402
+            }
403
+            BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
404
+                             ctx.event_handle,::boost::detail::win32::infinite,0));
405
+        }
406
+    }
407
+    template<typename Function, typename T1>
408
+    void call_once(once_flag& flag,Function f, T1 p1)
409
+    {
410
+        // Try for a quick win: if the procedure has already been called
411
+        // just skip through:
412
+        detail::once_context ctx;
413
+        while(::boost::detail::interlocked_read_acquire(&flag.status)
414
+              !=ctx.function_complete_flag_value)
415
+        {
416
+            if(detail::enter_once_region(flag, ctx))
417
+            {
418
+                BOOST_TRY
419
+                {
420
+                  BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
421
+                }
422
+                BOOST_CATCH(...)
423
+                {
424
+                    detail::rollback_once_region(flag, ctx);
425
+                    BOOST_RETHROW
426
+                }
427
+                BOOST_CATCH_END
428