1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2018-2018. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 //////////////////////////////////////////////////////////////////////////////
11 //
12 // This code is partially based on the lightweight mutex implemented
13 // by Boost.SmartPtr:
14 //
15 //  Copyright (c) 2002, 2003 Peter Dimov
16 //  Copyright (c) Microsoft Corporation 2014
17 //
18 // Distributed under the Boost Software License, Version 1.0. (See
19 // accompanying file LICENSE_1_0.txt or copy at
20 // http://www.boost.org/LICENSE_1_0.txt)
21 //
22 //////////////////////////////////////////////////////////////////////////////
23 
24 #ifndef BOOST_CONFIG_HPP
25 #  include <boost/config.hpp>
26 #endif
27 #
28 #if defined(BOOST_HAS_PRAGMA_ONCE)
29 #  pragma once
30 #endif
31 
32 #ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
33 #define BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
34 
35 #include <boost/container/detail/config_begin.hpp>
36 #include <boost/container/detail/workaround.hpp>
37 
38 #if defined(BOOST_HAS_PTHREADS)
39 
40 #include <pthread.h>
41 #include <boost/assert.hpp>
42 
43 namespace boost{
44 namespace container {
45 namespace dtl {
46 
47 class thread_mutex
48 {
49    public:
thread_mutex()50    thread_mutex()
51    {
52       BOOST_VERIFY(pthread_mutex_init(&m_mut, 0) == 0);
53    }
54 
~thread_mutex()55    ~thread_mutex()
56    {
57      BOOST_VERIFY(pthread_mutex_destroy(&m_mut) == 0);
58    }
59 
lock()60    void lock()
61    {
62       BOOST_VERIFY(pthread_mutex_lock( &m_mut) == 0);
63    }
64 
unlock()65    void unlock()
66    {
67       BOOST_VERIFY(pthread_mutex_unlock(&m_mut) == 0);
68    }
69 
70    private:
71    thread_mutex(thread_mutex const &);
72    thread_mutex & operator=(thread_mutex const &);
73 
74    pthread_mutex_t m_mut;
75 };
76 
77 } // namespace dtl {
78 } // namespace container {
79 } // namespace boost {
80 
81 #else //!BOOST_HAS_PTHREADS (Windows implementation)
82 
83 #ifdef BOOST_USE_WINDOWS_H
84 
85 #include <windows.h>
86 
87 namespace boost{
88 namespace container {
89 namespace dtl {
90 
91 typedef ::CRITICAL_SECTION win_critical_section;
92 
93 } // namespace dtl {
94 } // namespace container {
95 } // namespace boost {
96 
97 #else //! BOOST_USE_WINDOWS_H
98 
99 struct _RTL_CRITICAL_SECTION_DEBUG;
100 struct _RTL_CRITICAL_SECTION;
101 
102 namespace boost{
103 namespace container {
104 namespace dtl {
105 
106 #ifdef BOOST_PLAT_WINDOWS_UWP
107 extern "C" __declspec(dllimport) int __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
108 #else
109 extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
110 #endif
111 extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
112 extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
113 extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
114 
115 struct win_critical_section
116 {
117    struct _RTL_CRITICAL_SECTION_DEBUG * DebugInfo;
118    long LockCount;
119    long RecursionCount;
120    void * OwningThread;
121    void * LockSemaphore;
122    #if defined(_WIN64)
123    unsigned __int64 SpinCount;
124    #else
125    unsigned long SpinCount;
126    #endif
127 };
128 
129 } // namespace dtl {
130 } // namespace container {
131 } // namespace boost {
132 
133 #endif   //BOOST_USE_WINDOWS_H
134 
135 namespace boost{
136 namespace container {
137 namespace dtl {
138 
139 class thread_mutex
140 {
141    public:
thread_mutex()142    thread_mutex()
143    {
144       #ifdef BOOST_PLAT_WINDOWS_UWP
145       (InitializeCriticalSectionEx)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect), 4000, 0);
146       #else
147       (InitializeCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
148       #endif
149    }
150 
lock()151    void lock()
152    {
153       (EnterCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
154    }
155 
unlock()156    void unlock()
157    {
158       (LeaveCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
159    }
160 
~thread_mutex()161    ~thread_mutex()
162    {
163       (DeleteCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
164    }
165 
166    private:
167    thread_mutex(thread_mutex const &);
168    thread_mutex & operator=(thread_mutex const &);
169 
170    win_critical_section m_crit_sect;
171 };
172 
173 } // namespace dtl {
174 } // namespace container {
175 } // namespace boost {
176 
177 #endif   //BOOST_HAS_PTHREADS
178 
179 #include <boost/container/detail/config_end.hpp>
180 
181 #endif // #ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
182