1 /** \file lvptrvec.h 2 \brief pointer vector template 3 4 Multyplatform threads support. 5 6 CoolReader Engine 7 8 (c) Vadim Lopatin, 2000-2006 9 This source code is distributed under the terms of 10 GNU General Public License. 11 12 See LICENSE file for details. 13 14 */ 15 16 #ifndef __LVTHREAD_H_INCLUDED__ 17 #define __LVTHREAD_H_INCLUDED__ 18 19 #include <stdlib.h> 20 21 #if (CR_USE_THREADS==1) 22 23 #if defined(_LINUX) 24 #include <pthread.h> 25 26 class LVThread { 27 private: 28 pthread_t _thread; 29 bool _valid; 30 bool _stopped; start_routine(void * param)31 static void * start_routine(void * param) 32 { 33 LVThread * thread = (LVThread*)param; 34 thread->run(); 35 thread->_stopped = true; 36 return NULL; 37 } 38 protected: run()39 virtual void run() 40 { 41 } 42 public: start()43 virtual void start() 44 { 45 _valid = (pthread_create(&_thread, NULL, &start_routine, this) == 0); 46 } stopped()47 bool stopped() 48 { 49 return _stopped; 50 } join()51 void join() 52 { 53 if ( _valid ) { 54 void * res; 55 pthread_join( _thread, &res ); 56 _valid = false; 57 } 58 } LVThread()59 LVThread() 60 : _valid(false), _stopped(false) 61 { 62 } ~LVThread()63 virtual ~LVThread() 64 { 65 if ( _valid ) { 66 pthread_detach( _thread ); 67 } 68 } 69 }; 70 71 class LVMutex { 72 private: 73 pthread_mutex_t _mutex; 74 bool _valid; 75 public: LVMutex()76 LVMutex() 77 { 78 _valid = ( pthread_mutex_init(&_mutex, NULL) !=0 ); 79 } ~LVMutex()80 ~LVMutex() 81 { 82 if ( _valid ) 83 pthread_mutex_destroy( &_mutex ); 84 } lock()85 bool lock() 86 { 87 if ( _valid ) 88 return (pthread_mutex_lock( &_mutex )==0); 89 return false; 90 } trylock()91 bool trylock() 92 { 93 if ( _valid ) 94 return (pthread_mutex_trylock( &_mutex )==0); 95 return false; 96 } unlock()97 void unlock() 98 { 99 if ( _valid ) 100 pthread_mutex_unlock( &_mutex ); 101 } 102 }; 103 104 #elif defined(_WIN32) 105 106 class LVThread { 107 private: 108 HANDLE _thread; 109 bool _valid; 110 bool _stopped; 111 DWORD _id; 112 start_routine(LPVOID param)113 static DWORD WINAPI start_routine( 114 LPVOID param 115 ) 116 { 117 LVThread * thread = (LVThread*)param; 118 thread->run(); 119 thread->_stopped = true; 120 return 0; 121 } 122 protected: run()123 virtual void run() 124 { 125 } 126 public: start()127 virtual void start() 128 { 129 ResumeThread( _thread ); 130 } stopped()131 bool stopped() 132 { 133 return _stopped; 134 } join()135 void join() 136 { 137 if ( _valid ) { 138 WaitForSingleObject( _thread, INFINITE ); 139 _valid = false; 140 } 141 } LVThread()142 LVThread() 143 : _stopped(false) 144 { 145 _thread = CreateThread(NULL, 0, start_routine, this, CREATE_SUSPENDED, &_id ); 146 _valid = _thread != NULL; 147 } ~LVThread()148 virtual ~LVThread() 149 { 150 if ( _valid ) { 151 CloseHandle( _thread ); 152 } 153 } 154 }; 155 156 class LVMutex { 157 private: 158 HANDLE _mutex; 159 bool _valid; 160 public: LVMutex()161 LVMutex() 162 { 163 _mutex = CreateMutex( NULL, FALSE, NULL ); 164 _valid = (_mutex != NULL); 165 } ~LVMutex()166 ~LVMutex() 167 { 168 if ( _valid ) 169 CloseHandle( _mutex ); 170 } lock()171 bool lock() 172 { 173 if ( _valid ) { 174 return WaitForSingleObject( _mutex, INFINITE ) == WAIT_OBJECT_0; 175 } 176 return false; 177 } trylock()178 bool trylock() 179 { 180 if ( _valid ){ 181 return WaitForSingleObject( _mutex, 0 ) == WAIT_OBJECT_0; 182 } 183 return false; 184 } unlock()185 void unlock() 186 { 187 if ( _valid ) 188 ReleaseMutex( _mutex ); 189 } 190 }; 191 192 193 #endif 194 195 #else // CR_USE_THREADS 196 197 class LVThread { 198 protected: run()199 virtual void run() 200 { 201 } 202 public: start()203 virtual void start() 204 { 205 // fake: simulate execution here 206 run(); 207 } stopped()208 bool stopped() 209 { 210 return true; 211 } join()212 void join() 213 { 214 } LVThread()215 LVThread() 216 { 217 } ~LVThread()218 virtual ~LVThread() 219 { 220 } 221 }; 222 223 224 class LVMutex { 225 public: LVMutex()226 LVMutex() 227 { 228 } ~LVMutex()229 ~LVMutex() 230 { 231 } lock()232 bool lock() 233 { 234 return true; 235 } trylock()236 bool trylock() 237 { 238 return true; 239 } unlock()240 void unlock() 241 { 242 } 243 }; 244 245 #endif 246 247 class LVLock { 248 LVMutex &_mutex; 249 bool _locked; 250 LVLock & operator = (LVLock&) { 251 // no assignment 252 return *this; 253 } 254 public: LVLock(LVMutex & mutex)255 LVLock( LVMutex &mutex ) 256 : _mutex(mutex) 257 { 258 _locked = _mutex.lock(); 259 } ~LVLock()260 ~LVLock() 261 { 262 if ( _locked ) 263 _mutex.unlock(); 264 } 265 }; 266 267 268 #endif 269