1 /* 2 Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file 3 4 This file is part of libzmq, the ZeroMQ core engine in C++. 5 6 libzmq is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License (LGPL) as published 8 by the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 As a special exception, the Contributors give you permission to link 12 this library with independent modules to produce an executable, 13 regardless of the license terms of these independent modules, and to 14 copy and distribute the resulting executable under terms of your choice, 15 provided that you also meet, for each linked independent module, the 16 terms and conditions of the license of that module. An independent 17 module is a module which is not derived from or based on this library. 18 If you modify this library, you must extend this exception to your 19 version of the library. 20 21 libzmq is distributed in the hope that it will be useful, but WITHOUT 22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 License for more details. 25 26 You should have received a copy of the GNU Lesser General Public License 27 along with this program. If not, see <http://www.gnu.org/licenses/>. 28 */ 29 30 #ifndef __ZMQ_MUTEX_HPP_INCLUDED__ 31 #define __ZMQ_MUTEX_HPP_INCLUDED__ 32 33 #include "err.hpp" 34 #include "macros.hpp" 35 36 // Mutex class encapsulates OS mutex in a platform-independent way. 37 38 #ifdef ZMQ_HAVE_WINDOWS 39 40 #include "windows.hpp" 41 42 namespace zmq 43 { 44 class mutex_t 45 { 46 public: mutex_t()47 mutex_t () { InitializeCriticalSection (&_cs); } 48 ~mutex_t()49 ~mutex_t () { DeleteCriticalSection (&_cs); } 50 lock()51 void lock () { EnterCriticalSection (&_cs); } 52 try_lock()53 bool try_lock () { return (TryEnterCriticalSection (&_cs)) ? true : false; } 54 unlock()55 void unlock () { LeaveCriticalSection (&_cs); } 56 get_cs()57 CRITICAL_SECTION *get_cs () { return &_cs; } 58 59 private: 60 CRITICAL_SECTION _cs; 61 62 ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t) 63 }; 64 } 65 66 #elif defined ZMQ_HAVE_VXWORKS 67 68 #include <vxWorks.h> 69 #include <semLib.h> 70 71 namespace zmq 72 { 73 class mutex_t 74 { 75 public: mutex_t()76 inline mutex_t () 77 { 78 _semId = 79 semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 80 } 81 ~mutex_t()82 inline ~mutex_t () { semDelete (_semId); } 83 lock()84 inline void lock () { semTake (_semId, WAIT_FOREVER); } 85 try_lock()86 inline bool try_lock () 87 { 88 if (semTake (_semId, NO_WAIT) == OK) { 89 return true; 90 } 91 return false; 92 } 93 unlock()94 inline void unlock () { semGive (_semId); } 95 96 private: 97 SEM_ID _semId; 98 99 ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t) 100 }; 101 } 102 103 #else 104 105 #include <pthread.h> 106 107 namespace zmq 108 { 109 class mutex_t 110 { 111 public: mutex_t()112 inline mutex_t () 113 { 114 int rc = pthread_mutexattr_init (&_attr); 115 posix_assert (rc); 116 117 rc = pthread_mutexattr_settype (&_attr, PTHREAD_MUTEX_RECURSIVE); 118 posix_assert (rc); 119 120 rc = pthread_mutex_init (&_mutex, &_attr); 121 posix_assert (rc); 122 } 123 ~mutex_t()124 inline ~mutex_t () 125 { 126 int rc = pthread_mutex_destroy (&_mutex); 127 posix_assert (rc); 128 129 rc = pthread_mutexattr_destroy (&_attr); 130 posix_assert (rc); 131 } 132 lock()133 inline void lock () 134 { 135 int rc = pthread_mutex_lock (&_mutex); 136 posix_assert (rc); 137 } 138 try_lock()139 inline bool try_lock () 140 { 141 int rc = pthread_mutex_trylock (&_mutex); 142 if (rc == EBUSY) 143 return false; 144 145 posix_assert (rc); 146 return true; 147 } 148 unlock()149 inline void unlock () 150 { 151 int rc = pthread_mutex_unlock (&_mutex); 152 posix_assert (rc); 153 } 154 get_mutex()155 inline pthread_mutex_t *get_mutex () { return &_mutex; } 156 157 private: 158 pthread_mutex_t _mutex; 159 pthread_mutexattr_t _attr; 160 161 ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t) 162 }; 163 } 164 165 #endif 166 167 168 namespace zmq 169 { 170 struct scoped_lock_t 171 { scoped_lock_tzmq::scoped_lock_t172 scoped_lock_t (mutex_t &mutex_) : _mutex (mutex_) { _mutex.lock (); } 173 ~scoped_lock_tzmq::scoped_lock_t174 ~scoped_lock_t () { _mutex.unlock (); } 175 176 private: 177 mutex_t &_mutex; 178 179 ZMQ_NON_COPYABLE_NOR_MOVABLE (scoped_lock_t) 180 }; 181 182 183 struct scoped_optional_lock_t 184 { scoped_optional_lock_tzmq::scoped_optional_lock_t185 scoped_optional_lock_t (mutex_t *mutex_) : _mutex (mutex_) 186 { 187 if (_mutex != NULL) 188 _mutex->lock (); 189 } 190 ~scoped_optional_lock_tzmq::scoped_optional_lock_t191 ~scoped_optional_lock_t () 192 { 193 if (_mutex != NULL) 194 _mutex->unlock (); 195 } 196 197 private: 198 mutex_t *_mutex; 199 200 ZMQ_NON_COPYABLE_NOR_MOVABLE (scoped_optional_lock_t) 201 }; 202 } 203 204 #endif 205