1 // ---------------------------------------------------------------------------- 2 // 3 // Copyright (C) 2010-2016 Fons Adriaensen <fons@linuxaudio.org> 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // ---------------------------------------------------------------------------- 19 20 21 #ifndef __PXTHREAD_H 22 #define __PXTHREAD_H 23 24 25 // ---------------------------------------------------------------------------- 26 27 28 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(__APPLE__) || defined(__FreeBSD__) 29 30 // NOTE: __FreeBSD_kernel__ and __GNU__ were added by the Debian maintainers 31 // (the latter for the HURD version of Debian). Things are reported to work 32 // with some applications but probably have not been tested in depth. 33 34 35 #include <unistd.h> 36 #include <pthread.h> 37 #include <semaphore.h> 38 39 40 class Pxthread 41 { 42 public: 43 44 Pxthread (void); 45 virtual ~Pxthread (void); 46 Pxthread (const Pxthread&); 47 Pxthread& operator=(const Pxthread&); 48 49 virtual void thr_main (void) = 0; 50 virtual int thr_start (int policy, int priority, size_t stacksize = 0); 51 52 private: 53 54 pthread_t _thrid; 55 }; 56 57 58 #endif 59 60 61 // ---------------------------------------------------------------------------- 62 63 64 #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) 65 66 class Pxsema 67 { 68 public: 69 Pxsema(void)70 Pxsema (void) { init (0, 0); } ~Pxsema(void)71 ~Pxsema (void) { sem_destroy (&_sema); } 72 73 Pxsema (const Pxsema&); // disabled 74 Pxsema& operator= (const Pxsema&); // disabled 75 init(int s,int v)76 int init (int s, int v) { return sem_init (&_sema, s, v); } post(void)77 int post (void) { return sem_post (&_sema); } wait(void)78 int wait (void) { return sem_wait (&_sema); } trywait(void)79 int trywait (void) { return sem_trywait (&_sema); } 80 81 private: 82 83 sem_t _sema; 84 }; 85 86 #define PXSEMA_IS_IMPLEMENTED 87 #endif 88 89 90 // ---------------------------------------------------------------------------- 91 92 93 #ifdef __APPLE__ 94 95 96 // NOTE: ***** I DO NOT REPEAT NOT PROVIDE SUPPORT FOR OSX ***** 97 // 98 // The following code partially emulates the POSIX sem_t for which 99 // OSX has only a crippled implementation. It may or may not compile, 100 // and if it compiles it may or may not work correctly. Blame APPLE 101 // for not following POSIX standards. 102 103 104 #include <unistd.h> 105 #include <pthread.h> 106 107 108 class Pxsema 109 { 110 public: 111 Pxsema(void)112 Pxsema (void) : _count (0) 113 { 114 init (0, 0); 115 } 116 ~Pxsema(void)117 ~Pxsema (void) 118 { 119 pthread_mutex_destroy (&_mutex); 120 pthread_cond_destroy (&_cond); 121 } 122 123 Pxsema (const Pxsema&); // disabled 124 Pxsema& operator= (const Pxsema&); // disabled 125 init(int s,int v)126 int init (int s, int v) 127 { 128 _count = v; 129 return pthread_mutex_init (&_mutex, 0) || pthread_cond_init (&_cond, 0); 130 } 131 post(void)132 int post (void) 133 { 134 pthread_mutex_lock (&_mutex); 135 _count++; 136 if (_count == 1) pthread_cond_signal (&_cond); 137 pthread_mutex_unlock (&_mutex); 138 return 0; 139 } 140 wait(void)141 int wait (void) 142 { 143 pthread_mutex_lock (&_mutex); 144 while (_count < 1) pthread_cond_wait (&_cond, &_mutex); 145 _count--; 146 pthread_mutex_unlock (&_mutex); 147 return 0; 148 } 149 trywait(void)150 int trywait (void) 151 { 152 if (pthread_mutex_trylock (&_mutex)) return -1; 153 if (_count < 1) 154 { 155 pthread_mutex_unlock (&_mutex); 156 return -1; 157 } 158 _count--; 159 pthread_mutex_unlock (&_mutex); 160 return 0; 161 } 162 163 private: 164 165 int _count; 166 pthread_mutex_t _mutex; 167 pthread_cond_t _cond; 168 }; 169 170 #define PXSEMA_IS_IMPLEMENTED 171 #endif 172 173 174 // ---------------------------------------------------------------------------- 175 176 177 #if defined(_WIN32) || defined(WIN32) 178 179 #include <windows.h> 180 181 182 #define usleep(t) Sleep ((t) / 1000); 183 184 #define SCHED_OTHER 0 185 #define SCHED_FIFO 1 186 #define SCHED_RR 2 187 188 189 // --------------------------------------------------------------------- 190 // 191 // Mapping of policy and priority pararmeters on Windows 192 // 193 // If the policy parameter is SCHED_FIFO or SCHED_RR then 194 // 195 // priority parameter Windows thread priority 196 // ------------------------------------------------ 197 // < 60 THREAD_PRIORITY_TIME_CRITICAL 198 // 60..69 MMCSS Pro Audio, LOW 199 // 70..79 MMCSS Pro Audio, NORMAL 200 // 80..89 MMCSS Pro Audio, HIGH 201 // >= 90 MMCSS Pro Audio, CRITICAL 202 // 203 // If the policy parameter is not SCHED_FIFO or SCHED_RR then 204 // the default thread priority is used. 205 // 206 // --------------------------------------------------------------------- 207 208 209 class Pxthread 210 { 211 public: 212 213 Pxthread (void); 214 virtual ~Pxthread (void); 215 Pxthread (const Pxthread&); 216 Pxthread& operator=(const Pxthread&); 217 handle(void)218 void *handle (void) { return _handle; } priority(void)219 int priority (void) { return _prior; } 220 221 virtual void thr_main (void) = 0; 222 int thr_start (int policy, int priority, size_t stacksize = 0); 223 224 void mmcssprio (void); 225 226 private: 227 228 void *_handle; 229 unsigned long _thrid; 230 int _prior; 231 232 233 static unsigned long _index; 234 }; 235 236 237 class Pxsema 238 { 239 public: 240 Pxsema(void)241 Pxsema (void) { _handle = CreateSemaphore (0, 0, 999999999, 0); } ~Pxsema(void)242 ~Pxsema (void) { CloseHandle (_handle); } 243 244 Pxsema (const Pxsema&); // disabled 245 Pxsema& operator= (const Pxsema&); // disabled 246 247 // int init (void) { return 0; } post(void)248 int post (void) { return ReleaseSemaphore (_handle, 1, 0) ? 0 : -1; } wait(void)249 int wait (void) { return WaitForSingleObject (_handle, INFINITE); } trywait(void)250 int trywait (void) { return WaitForSingleObject (_handle, 0); } 251 252 private: 253 254 void *_handle; 255 }; 256 257 258 #define PXSEMA_IS_IMPLEMENTED 259 #endif 260 261 262 // ---------------------------------------------------------------------------- 263 264 265 #ifndef PXSEMA_IS_IMPLEMENTED 266 #error "The Pxsema class is not implemented." 267 #endif 268 269 270 #endif 271