Merge amd64 NDK from amd64 branch:
[reactos.git] / irc / ArchBlackmann / ReliMT.h
1 // ReliMT.h
2 // lots of code here is (c) Bartosz Milewski, 1996, www.relisoft.com
3 // The rest is (C) 2003-2004 Royce Mitchell III
4 // and released under the LGPL & BSD licenses
5
6
7 #ifndef __RELIMT_H
8 #define __RELIMT_H
9
10 #include "Reli.h"
11
12 #ifdef WIN32
13 # ifndef _WINDOWS_
14 # define WIN32_LEAN_AND_MEAN
15 # include <windows.h>
16 # endif
17 # define THREADAPI WINAPI
18 #elif defined(UNIX)
19 # include <pthread.h>
20 # include <stdlib.h>
21 # include "string.h"
22 # include <sys/types.h> //Semaphore
23 # include <sys/ipc.h> //Semaphore
24 # include <sys/sem.h> //Semaphore
25 # define THREADAPI
26 #else
27 # error unrecognized target
28 #endif
29
30
31 ////////////////////////////////////////////////////////////////////////////////
32 // Thread
33
34 class Thread : public Uncopyable
35 {
36 public:
37 Thread ( long (THREADAPI * pFun) (void* arg), void* pArg );
38 ~Thread();
39 //void Resume();
40 void WaitForDeath();
41
42 // platform-specific stuff:
43 private:
44 #ifdef WIN32
45 HANDLE _handle;
46 DWORD _tid; // thread id
47 #elif defined(UNIX)
48 pthread_t _threadId; // id of the thread
49 #else
50 # error unrecognized target
51 #endif
52 //DECLARE_PTR(Thread,(long (THREADAPI * pFun) (void* arg), void* pArg),(pFun,pArg));
53 }; //DECLARE_SPTR(Thread,(long (THREADAPI * pFun) (void* arg), void* pArg),(pFun,pArg));
54
55 ////////////////////////////////////////////////////////////////////////////////
56 // ActiveObject
57
58 class ActiveObject : public Uncopyable
59 {
60 public:
61 ActiveObject();
62 virtual ~ActiveObject();
63 void Kill();
64 void Start();
65
66 protected:
67 virtual void InitThread() = 0;
68 virtual void Run() = 0;
69 virtual void FlushThread() = 0;
70
71 int _isDying;
72
73 static long THREADAPI ThreadEntry ( void *pArg );
74 Thread *_thread;
75
76 //DECLARE_PTRV(ActiveObject);
77 }; //DECLARE_SPTRV(ActiveObject);
78
79 // Last thing in the constructor of a class derived from
80 // ActiveObject you must call
81 // Start();
82 // Inside the loop the Run method you must keep checking _isDying
83 // if (_isDying)
84 // return;
85 // FlushThread must reset all the events on which the thread might be waiting.
86 // Example:
87 #if 0
88 // MyAsyncOutputter - class that outputs strings to a file asynchronously
89 class MyAsyncOutputter : public ActiveObject
90 {
91 public:
92 MyAsyncOutputter ( const string& filename ) : _filename(filename), _currentBuf(0)
93 {
94 Start(); // start thread
95 }
96 void InitThread()
97 {
98 _f.open ( _filename, "wb" );
99 }
100 void Output ( const string& s )
101 {
102 {
103 // acquire lock long enough to add the string to the active buffer
104 Mutex::Lock lock ( _mutex );
105 _buf[_currentBuf].push_back ( s );
106 }
107 _event.Release(); // don't need the lock fire the event
108 }
109 void Run()
110 {
111 while ( !_isDying )
112 {
113 // wait for signal from Output() or FlushThread()
114 _event.Wait();
115 {
116 // acquire lock long enough to switch active buffers
117 Mutex::Lock lock ( _mutex );
118 _currentBuf = 1-_currentBuf;
119 ASSERT ( !_buf[_currentBuf].size() );
120 }
121 // get a reference to the old buffer
122 vector<string>& buf = _buf[1-_currentBuf];
123 // write each string out to file and then empty the buffer
124 for ( int i = 0; i < buf.size(); i++ )
125 _f.write ( buf[i].c_str(), buf[i].size() );
126 buf.resize(0);
127 }
128 }
129 void FlushThread()
130 {
131 // _isDying is already set: signal thread so it can see that too
132 _event.Release();
133 }
134 private:
135 string _filename;
136 File _f;
137 int _currentBuf;
138 vector<string> _buf[2];
139 Event _event;
140 Mutex _mutex;
141 };
142 #endif
143
144 ////////////////////////////////////////////////////////////////////////////////
145 // Mutex
146
147 class Mutex : public Uncopyable
148 {
149 public:
150 Mutex();
151 ~Mutex();
152 private:
153 void Acquire();
154 bool TryAcquire();
155 void Release();
156 public:
157 // sub-class used to lock the Mutex
158 class Lock : public Uncopyable
159 {
160 public:
161 Lock ( Mutex& m );
162 ~Lock();
163
164 private:
165 // private data
166 Mutex& _m;
167 };
168 friend class Mutex::Lock;
169
170
171 // sub-class used to attempt to lock the mutex. Use operator bool()
172 // to test if the lock was successful
173 class TryLock : public Uncopyable
174 {
175 public:
176 TryLock ( Mutex& m );
177 ~TryLock();
178 operator bool () { return _bLocked; }
179
180 private:
181 // private data
182 bool _bLocked;
183 Mutex& _m;
184 };
185 friend class Mutex::TryLock;
186
187 private:
188 // platform-specific stuff:
189 #ifdef WIN32
190 HANDLE _h;
191 #elif defined(UNIX)
192 pthread_mutex_t _mutex;
193 public: operator pthread_mutex_t* () { return &_mutex; }
194 #else
195 # error unrecognized target
196 #endif
197 };
198
199 ////////////////////////////////////////////////////////////////////////////////
200 // Event
201
202 class Event : public Uncopyable
203 {
204 public:
205 Event();
206 ~Event();
207 void Release(); // put into signaled state
208 void Wait();
209
210 private:
211 #ifdef WIN32
212 HANDLE _handle;
213 #elif defined(UNIX)
214 //Sem util functions
215 void sem_init();
216 int sem_P();
217 int sem_V();
218 void sem_destroy();
219
220 int sem_id;
221 //pthread_cond_t _cond;
222 //Mutex _mutex;
223 #else
224 # error unrecognized target
225 #endif
226 //DECLARE_PTR(Event,(),());
227 }; //DECLARE_SPTR(Event,(),());
228
229 #endif//__RELIWIN32_H