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