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/regex/config.hpp>
21 
22 #if defined(BOOST_REGEX_CXX03)
23 
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
34 #ifndef WIN32_LEAN_AND_MEAN
35 #  define WIN32_LEAN_AND_MEAN
36 #endif
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 
scoped_static_mutex_lock(static_mutex & m,bool lk)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 
~scoped_static_mutex_lock()53 scoped_static_mutex_lock::~scoped_static_mutex_lock()
54 {
55    if(m_have_lock)
56       unlock();
57 }
58 
lock()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 
unlock()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
189 #endif
190