• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
39 namespace boost{
40 
41 #if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER)
42 
scoped_static_mutex_lock(static_mutex & m,bool lk)43 scoped_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 
~scoped_static_mutex_lock()50 scoped_static_mutex_lock::~scoped_static_mutex_lock()
51 {
52    if(m_have_lock)
53       unlock();
54 }
55 
lock()56 void 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 
unlock()65 void 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 
79 BOOST_STATIC_ASSERT(sizeof(LONG) == sizeof(boost::int32_t));
80 
81 scoped_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 
88 scoped_static_mutex_lock::~scoped_static_mutex_lock()
89 {
90    if(m_have_lock)
91       unlock();
92 }
93 
94 void 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 
110 void 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 
130 boost::recursive_mutex* static_mutex::m_pmutex = 0;
131 boost::once_flag static_mutex::m_once = BOOST_ONCE_INIT;
132 
133 extern "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 
139 void 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 
146 scoped_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 
153 scoped_static_mutex_lock::~scoped_static_mutex_lock()
154 {
155    if(m_have_lock)
156       unlock();
157    delete m_plock;
158 }
159 
160 void 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 
172 void 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