]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * | |
3 | * Copyright (c) 2004 | |
4 | * John Maddock | |
5 | * | |
6 | * Use, modification and distribution are subject to the | |
7 | * Boost Software License, Version 1.0. (See accompanying file | |
8 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | * | |
10 | */ | |
11 | ||
12 | /* | |
13 | * LOCATION: see http://www.boost.org for most recent version. | |
14 | * FILE static_mutex.cpp | |
15 | * VERSION see <boost/version.hpp> | |
16 | * DESCRIPTION: Declares static_mutex lock type. | |
17 | */ | |
18 | ||
19 | #define BOOST_REGEX_SOURCE | |
1e59de90 TL |
20 | #include <boost/regex/config.hpp> |
21 | ||
22 | #if defined(BOOST_REGEX_CXX03) | |
23 | ||
7c673cae FG |
24 | #include <boost/assert.hpp> |
25 | ||
26 | #ifdef BOOST_HAS_THREADS | |
27 | ||
28 | #include <boost/regex/pending/static_mutex.hpp> | |
29 | ||
30 | #if defined(BOOST_HAS_WINTHREADS) | |
31 | #ifndef NOMINMAX | |
32 | # define NOMINMAX | |
33 | #endif | |
92f5a8d4 TL |
34 | #ifndef WIN32_LEAN_AND_MEAN |
35 | # define WIN32_LEAN_AND_MEAN | |
36 | #endif | |
7c673cae FG |
37 | #include <windows.h> |
38 | #include <boost/static_assert.hpp> | |
39 | #endif | |
40 | ||
41 | ||
42 | namespace boost{ | |
43 | ||
44 | #if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER) | |
45 | ||
46 | scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& m, bool lk) | |
47 | : m_mutex(m), m_have_lock(false) | |
48 | { | |
49 | if(lk) | |
50 | lock(); | |
51 | } | |
52 | ||
53 | scoped_static_mutex_lock::~scoped_static_mutex_lock() | |
54 | { | |
55 | if(m_have_lock) | |
56 | unlock(); | |
57 | } | |
58 | ||
59 | void scoped_static_mutex_lock::lock() | |
60 | { | |
61 | if(0 == m_have_lock) | |
62 | { | |
63 | // Client code will throw if this fails: | |
64 | m_have_lock = (pthread_mutex_lock(&(m_mutex.m_mutex)) == 0); | |
65 | } | |
66 | } | |
67 | ||
68 | void scoped_static_mutex_lock::unlock() | |
69 | { | |
70 | if(m_have_lock) | |
71 | { | |
72 | // If this fails there's nothing we can do except assert, | |
73 | // exceptions are out of the question as this code is called | |
74 | // from the lock's destructor: | |
75 | BOOST_VERIFY(pthread_mutex_unlock(&(m_mutex.m_mutex)) == 0); | |
76 | m_have_lock = false; | |
77 | } | |
78 | } | |
79 | ||
80 | #elif defined(BOOST_HAS_WINTHREADS) | |
81 | ||
82 | BOOST_STATIC_ASSERT(sizeof(LONG) == sizeof(boost::int32_t)); | |
83 | ||
84 | scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& m, bool lk) | |
85 | : m_mutex(m), m_have_lock(false) | |
86 | { | |
87 | if(lk) | |
88 | lock(); | |
89 | } | |
90 | ||
91 | scoped_static_mutex_lock::~scoped_static_mutex_lock() | |
92 | { | |
93 | if(m_have_lock) | |
94 | unlock(); | |
95 | } | |
96 | ||
97 | void scoped_static_mutex_lock::lock() | |
98 | { | |
99 | if(0 == m_have_lock) | |
100 | { | |
101 | #if !defined(InterlockedCompareExchangePointer) | |
102 | while(0 != InterlockedCompareExchange(reinterpret_cast<void**>((boost::uint_least16_t*)&(m_mutex.m_mutex)), (void*)1, 0)) | |
103 | #else | |
104 | while(0 != InterlockedCompareExchange(reinterpret_cast<LONG*>(&(m_mutex.m_mutex)), 1, 0)) | |
105 | #endif | |
106 | { | |
107 | Sleep(0); | |
108 | } | |
109 | m_have_lock = true; | |
110 | } | |
111 | } | |
112 | ||
113 | void scoped_static_mutex_lock::unlock() | |
114 | { | |
115 | if(m_have_lock) | |
116 | { | |
117 | #if !defined(InterlockedCompareExchangePointer) | |
118 | InterlockedExchange((LONG*)&(m_mutex.m_mutex), 0); | |
119 | #else | |
120 | InterlockedExchange(reinterpret_cast<LONG*>(&(m_mutex.m_mutex)), 0); | |
121 | #endif | |
122 | m_have_lock = false; | |
123 | } | |
124 | } | |
125 | ||
126 | #else | |
127 | // | |
128 | // Portable version of a static mutex based on Boost.Thread library: | |
129 | // | |
130 | #include <stdlib.h> | |
131 | #include <boost/assert.hpp> | |
132 | ||
133 | boost::recursive_mutex* static_mutex::m_pmutex = 0; | |
134 | boost::once_flag static_mutex::m_once = BOOST_ONCE_INIT; | |
135 | ||
136 | extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex() | |
137 | { | |
138 | delete static_mutex::m_pmutex; | |
139 | static_mutex::m_pmutex = 0; | |
140 | } | |
141 | ||
142 | void static_mutex::init() | |
143 | { | |
144 | m_pmutex = new boost::recursive_mutex(); | |
145 | int r = atexit(boost_regex_free_static_mutex); | |
146 | BOOST_ASSERT(0 == r); | |
147 | } | |
148 | ||
149 | scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& , bool lk) | |
150 | : m_plock(0), m_have_lock(false) | |
151 | { | |
152 | if(lk) | |
153 | lock(); | |
154 | } | |
155 | ||
156 | scoped_static_mutex_lock::~scoped_static_mutex_lock() | |
157 | { | |
158 | if(m_have_lock) | |
159 | unlock(); | |
160 | delete m_plock; | |
161 | } | |
162 | ||
163 | void scoped_static_mutex_lock::lock() | |
164 | { | |
165 | if(0 == m_have_lock) | |
166 | { | |
167 | boost::call_once(static_mutex::m_once,&static_mutex::init); | |
168 | if(0 == m_plock) | |
169 | m_plock = new boost::unique_lock<boost::recursive_mutex>(*static_mutex::m_pmutex, boost::defer_lock); | |
170 | m_plock->lock(); | |
171 | m_have_lock = true; | |
172 | } | |
173 | } | |
174 | ||
175 | void scoped_static_mutex_lock::unlock() | |
176 | { | |
177 | if(m_have_lock) | |
178 | { | |
179 | m_plock->unlock(); | |
180 | m_have_lock = false; | |
181 | } | |
182 | } | |
183 | ||
184 | #endif | |
185 | ||
186 | } | |
187 | ||
188 | #endif // BOOST_HAS_THREADS | |
1e59de90 | 189 | #endif |