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