blob: 850f04ddcbe89bcb0f171d6968f8342895294063 [file] [log] [blame]
Constantin Kaplinsky0a1eca12006-04-16 07:28:14 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19// -=- Threading_win32.h
20// Win32 Threading interface implementation
21
22#ifndef __RFB_THREADING_IMPL_WIN32
23#define __RFB_THREADING_IMPL_WIN32
24
25#define __RFB_THREADING_IMPL WIN32
26
27#include <rfb_win32/Handle.h>
28#include <rfb/util.h>
29#include <rdr/Exception.h>
30//#include <stdio.h>
31
32
33namespace rfb {
34
35 class Mutex {
36 public:
37 Mutex() {
38 InitializeCriticalSection(&crit);
39 }
40 ~Mutex() {
41 DeleteCriticalSection(&crit);
42 }
43 friend class Lock;
44 friend class Condition;
45 protected:
46 void enter() {EnterCriticalSection(&crit);}
47 void exit() {LeaveCriticalSection(&crit);}
48 CRITICAL_SECTION crit;
49 };
50
51 class Lock {
52 public:
53 Lock(Mutex& m) : mutex(m) {m.enter();}
54 ~Lock() {mutex.exit();}
55 protected:
56 Mutex& mutex;
57 };
58
59 enum ThreadState {ThreadCreated, ThreadStarted, ThreadStopped, ThreadJoined, ThreadNative};
60
61 class Thread {
62 public:
63 Thread(const char* name_=0);
64 virtual ~Thread();
65
66 virtual void run();
67
68 virtual void start();
69 virtual Thread* join();
70
71 const char* getName() const;
72 ThreadState getState() const;
73
74 // Determines whether the thread should delete itself when run() returns
75 // If you set this, you must NEVER call join()!
76 void setDeleteAfterRun() {deleteAfterRun = true;};
77
78 unsigned long getThreadId() const;
79
80 static Thread* self();
81
82 friend class Condition;
83
84 protected:
85 Thread(HANDLE thread_, DWORD thread_id_);
86 static DWORD WINAPI threadProc(LPVOID lpParameter);
87
88 win32::Handle thread;
89 DWORD thread_id;
90 CharArray name;
91 ThreadState state;
92 Condition* sig;
93 Mutex mutex;
94
95 win32::Handle cond_event;
96 Thread* cond_next;
97
98 bool deleteAfterRun;
99 };
100
101 class Condition {
102 public:
103 Condition(Mutex& m) : mutex(m), waiting(0) {
104 }
105 ~Condition() {
106 }
107
108 // Wake up the specified number of threads that are waiting
109 // on this Condition, or all of them if -1 is specified.
110 void signal(int howMany=1) {
111 Lock l(cond_lock);
112 while (waiting && howMany!=0) {
113 SetEvent(waiting->cond_event);
114 waiting = waiting->cond_next;
115 if (howMany>0) --howMany;
116 }
117 }
118
119 // NB: Must hold "mutex" to call wait()
120 // Wait until either the Condition is signalled or the timeout
121 // expires.
122 void wait(DWORD timeout=INFINITE) {
123 Thread* self = Thread::self();
124 ResetEvent(self->cond_event);
125 { Lock l(cond_lock);
126 self->cond_next = waiting;
127 waiting = self;
128 }
129 mutex.exit();
130 DWORD result = WaitForSingleObject(self->cond_event, timeout);
131 mutex.enter();
132 if (result == WAIT_TIMEOUT) {
133 Lock l(cond_lock);
134 // Remove this thread from the Condition
135 for (Thread** removeFrom = &waiting; *removeFrom; removeFrom = &(*removeFrom)->cond_next) {
136 if (*removeFrom == self) {
137 *removeFrom = self->cond_next;
138 break;
139 }
140 }
141 } else if (result == WAIT_FAILED) {
142 throw rdr::SystemException("failed to wait on Condition", GetLastError());
143 }
144 }
145
146 protected:
147 Mutex& mutex;
148 Mutex cond_lock;
149 Thread* waiting;
150 };
151
152};
153
154#endif // __RFB_THREADING_IMPL