1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 25 февр. 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef INCLUDE_CORE_IPC_MUTEX_H_ 23 #define INCLUDE_CORE_IPC_MUTEX_H_ 24 25 #include <core/types.h> 26 #include <dsp/atomic.h> 27 28 #if defined(PLATFORM_WINDOWS) 29 #include <synchapi.h> 30 #elif defined(PLATFORM_LINUX) 31 #include <linux/futex.h> 32 #include <sys/syscall.h> 33 #include <unistd.h> 34 #include <pthread.h> 35 #include <sched.h> 36 #include <errno.h> 37 #else 38 #include <pthread.h> 39 #include <sched.h> 40 #include <errno.h> 41 #endif 42 43 namespace lsp 44 { 45 namespace ipc 46 { 47 #if defined(PLATFORM_WINDOWS) 48 /** 49 * Recursive mutex for Windows platform 50 */ 51 class Mutex 52 { 53 private: 54 mutable HANDLE hMutex; // Mutex object 55 mutable DWORD nThreadId; // Owner's thread identifier 56 mutable atomic_t nLocks; // Number of locks by current thread 57 58 private: 59 Mutex & operator = (const Mutex & m); // Deny copying 60 61 public: 62 explicit Mutex(); 63 ~Mutex(); 64 65 /** Wait until mutex is unlocked and lock it 66 * 67 */ 68 bool lock() const; 69 70 /** Try to lock mutex and return status of operation 71 * 72 * @return non-zero value if mutex was locked 73 */ 74 bool try_lock() const; 75 76 /** Unlock mutex 77 * 78 */ 79 bool unlock() const; 80 }; 81 #elif defined(PLATFORM_LINUX) 82 /** Fast recursive mutex implementation for Linux 83 * 84 */ 85 class Mutex 86 { 87 private: 88 mutable volatile atomic_t nLock; // 1 = locked, 0 = locked 89 mutable pthread_t nThreadId; // Locked thread identifier 90 mutable atomic_t nLocks; // Number of locks by current thread 91 92 private: 93 Mutex & operator = (const Mutex & m); // Deny copying 94 95 public: 96 explicit Mutex() 97 { 98 nLock = 1; 99 nThreadId = -1; 100 nLocks = 0; 101 } 102 103 /** Wait until mutex is unlocked and lock it 104 * 105 */ 106 bool lock() const; 107 108 /** Try to lock mutex and return status of operation 109 * 110 * @return non-zero value if mutex was locked 111 */ 112 bool try_lock() const; 113 114 /** Unlock mutex 115 * 116 */ 117 bool unlock() const; 118 }; 119 #else 120 /** 121 * Recursive mutex implementation using pthread 122 */ 123 class Mutex 124 { 125 private: 126 mutable pthread_mutex_t sMutex; 127 128 private: 129 Mutex & operator = (const Mutex & m); // Deny copying 130 131 public: 132 explicit Mutex(); 133 ~Mutex(); 134 135 /** Wait until mutex is unlocked and lock it 136 * 137 */ 138 inline bool lock() const 139 { 140 while (true) 141 { 142 switch (pthread_mutex_lock(&sMutex)) 143 { 144 case 0: return true; 145 case EBUSY: 146 #ifdef PLATFORM_SOLARIS 147 sched_yield(); 148 #else 149 pthread_yield(); 150 #endif /* PLATFORM_SOLARIS */ 151 break; 152 default: return false; 153 } 154 } 155 } 156 157 /** Try to lock mutex and return status of operation 158 * 159 * @return non-zero value if mutex was locked 160 */ 161 inline bool try_lock() const 162 { 163 return pthread_mutex_trylock(&sMutex) == 0; 164 } 165 166 /** Unlock mutex 167 * 168 */ 169 inline bool unlock() const 170 { 171 return pthread_mutex_unlock(&sMutex) == 0; 172 } 173 }; 174 #endif 175 176 } /* namespace ipc */ 177 } /* namespace lsp */ 178 179 #endif /* INCLUDE_CORE_IPC_MUTEX_H_ */ 180