CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/vncdll/winvnc/omnithread/omnithread.h
Views: 11784
1
// Package : omnithread
2
// omnithread.h Created : 7/94 tjr
3
//
4
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
5
//
6
// This file is part of the omnithread library
7
//
8
// The omnithread library is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU Library General Public
10
// License as published by the Free Software Foundation; either
11
// version 2 of the License, or (at your option) any later version.
12
//
13
// This library is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
// Library General Public License for more details.
17
//
18
// You should have received a copy of the GNU Library General Public
19
// License along with this library; if not, write to the Free
20
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
// 02111-1307, USA
22
//
23
24
//
25
// Interface to OMNI thread abstraction.
26
//
27
// This file declares classes for threads and synchronisation objects
28
// (mutexes, condition variables and counting semaphores).
29
//
30
// Wherever a seemingly arbitrary choice has had to be made as to the interface
31
// provided, the intention here has been to be as POSIX-like as possible. This
32
// is why there is no semaphore timed wait, for example.
33
//
34
35
#ifndef __omnithread_h_
36
#define __omnithread_h_
37
38
#ifndef NULL
39
#define NULL (void*)0
40
#endif
41
42
class omni_mutex;
43
class omni_condition;
44
class omni_semaphore;
45
class omni_thread;
46
47
//
48
// OMNI_THREAD_EXPOSE can be defined as public or protected to expose the
49
// implementation class - this may be useful for debugging. Hopefully this
50
// won't change the underlying structure which the compiler generates so that
51
// this can work without recompiling the library.
52
//
53
54
#ifndef OMNI_THREAD_EXPOSE
55
#define OMNI_THREAD_EXPOSE private
56
#endif
57
58
59
//
60
// Include implementation-specific header file.
61
//
62
// This must define 4 CPP macros of the form OMNI_x_IMPLEMENTATION for mutex,
63
// condition variable, semaphore and thread. Each should define any
64
// implementation-specific members of the corresponding classes.
65
//
66
67
68
#if defined(__arm__) && defined(__atmos__)
69
#include <omnithread/posix.h>
70
71
#elif defined(__alpha__) && defined(__osf1__)
72
#include <omnithread/posix.h>
73
74
#elif defined(__powerpc__) && defined(__aix__)
75
#include <omnithread/posix.h>
76
77
#elif defined(__hpux__)
78
#include <omnithread/posix.h>
79
80
#elif defined(__WIN32__)
81
#include "nt.h"
82
83
#ifdef _MSC_VER
84
85
// Using MSVC++ to compile. If compiling library as a DLL,
86
// define _OMNITHREAD_DLL. If compiling as a statuc library, define
87
// _WINSTATIC
88
// If compiling an application that is to be statically linked to omnithread,
89
// define _WINSTATIC (if the application is to be dynamically linked,
90
// there is no need to define any of these macros).
91
92
#if defined (_OMNITHREAD_DLL) && defined(_WINSTATIC)
93
#error "Both _OMNITHREAD_DLL and _WINSTATIC are defined."
94
#elif defined(_OMNITHREAD_DLL)
95
#define _OMNITHREAD_NTDLL_ __declspec(dllexport)
96
#elif !defined(_WINSTATIC)
97
#define _OMNITHREAD_NTDLL_ __declspec(dllimport)
98
#elif defined(_WINSTATIC)
99
#define _OMNITHREAD_NTDLL_
100
#endif
101
// _OMNITHREAD_DLL && _WINSTATIC
102
103
#else
104
105
// Not using MSVC++ to compile
106
#define _OMNITHREAD_NTDLL_
107
108
#endif
109
// _MSC_VER
110
111
#elif defined(__sunos__) && (__OSVERSION__ == 5)
112
#ifdef UsePthread
113
#include <omnithread/posix.h>
114
#else
115
#include <omnithread/solaris.h>
116
#endif
117
118
#elif defined(__linux__)
119
#include <omnithread/posix.h>
120
121
#elif defined(__nextstep__)
122
#include <omnithread/mach.h>
123
124
#elif defined(__VMS)
125
#include <omnithread/posix.h>
126
127
#elif defined(__SINIX__)
128
#include <omnithread/posix.h>
129
130
#elif defined(__osr5__)
131
#include <omnithread/posix.h>
132
133
#elif defined(__irix__)
134
#include <omnithread/posix.h>
135
136
#else
137
#error "No implementation header file"
138
#endif
139
140
#if !defined(__WIN32__)
141
#define _OMNITHREAD_NTDLL_
142
#endif
143
144
#if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \
145
!defined(OMNI_CONDITION_IMPLEMENTATION) || \
146
!defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \
147
!defined(OMNI_THREAD_IMPLEMENTATION))
148
#error "Implementation header file incomplete"
149
#endif
150
151
152
//
153
// This exception is thrown in the event of a fatal error.
154
//
155
156
class _OMNITHREAD_NTDLL_ omni_thread_fatal {
157
public:
158
int error;
159
omni_thread_fatal(int e = 0) : error(e) {}
160
};
161
162
163
//
164
// This exception is thrown when an operation is invoked with invalid
165
// arguments.
166
//
167
168
class _OMNITHREAD_NTDLL_ omni_thread_invalid {};
169
170
171
///////////////////////////////////////////////////////////////////////////
172
//
173
// Mutex
174
//
175
///////////////////////////////////////////////////////////////////////////
176
177
class _OMNITHREAD_NTDLL_ omni_mutex {
178
179
public:
180
omni_mutex(void);
181
~omni_mutex(void);
182
183
void lock(void);
184
void unlock(void);
185
void acquire(void) { lock(); }
186
void release(void) { unlock(); }
187
// the names lock and unlock are preferred over acquire and release
188
// since we are attempting to be as POSIX-like as possible.
189
190
friend class omni_condition;
191
192
private:
193
// dummy copy constructor and operator= to prevent copying
194
omni_mutex(const omni_mutex&);
195
omni_mutex& operator=(const omni_mutex&);
196
197
OMNI_THREAD_EXPOSE:
198
OMNI_MUTEX_IMPLEMENTATION
199
};
200
201
//
202
// As an alternative to:
203
// {
204
// mutex.lock();
205
// .....
206
// mutex.unlock();
207
// }
208
//
209
// you can use a single instance of the omni_mutex_lock class:
210
//
211
// {
212
// omni_mutex_lock l(mutex);
213
// ....
214
// }
215
//
216
// This has the advantage that mutex.unlock() will be called automatically
217
// when an exception is thrown.
218
//
219
220
class _OMNITHREAD_NTDLL_ omni_mutex_lock {
221
omni_mutex& mutex;
222
public:
223
omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); }
224
~omni_mutex_lock(void) { mutex.unlock(); }
225
private:
226
// dummy copy constructor and operator= to prevent copying
227
omni_mutex_lock(const omni_mutex_lock&);
228
omni_mutex_lock& operator=(const omni_mutex_lock&);
229
};
230
231
232
///////////////////////////////////////////////////////////////////////////
233
//
234
// Condition variable
235
//
236
///////////////////////////////////////////////////////////////////////////
237
238
class _OMNITHREAD_NTDLL_ omni_condition {
239
240
omni_mutex* mutex;
241
242
public:
243
omni_condition(omni_mutex* m);
244
// constructor must be given a pointer to an existing mutex. The
245
// condition variable is then linked to the mutex, so that there is an
246
// implicit unlock and lock around wait() and timed_wait().
247
248
~omni_condition(void);
249
250
void wait(void);
251
// wait for the condition variable to be signalled. The mutex is
252
// implicitly released before waiting and locked again after waking up.
253
// If wait() is called by multiple threads, a signal may wake up more
254
// than one thread. See POSIX threads documentation for details.
255
256
int timedwait(unsigned long secs, unsigned long nanosecs = 0);
257
// timedwait() is given an absolute time to wait until. To wait for a
258
// relative time from now, use omni_thread::get_time. See POSIX threads
259
// documentation for why absolute times are better than relative.
260
// Returns 1 (true) if successfully signalled, 0 (false) if time
261
// expired.
262
263
void signal(void);
264
// if one or more threads have called wait(), signal wakes up at least
265
// one of them, possibly more. See POSIX threads documentation for
266
// details.
267
268
void broadcast(void);
269
// broadcast is like signal but wakes all threads which have called
270
// wait().
271
272
private:
273
// dummy copy constructor and operator= to prevent copying
274
omni_condition(const omni_condition&);
275
omni_condition& operator=(const omni_condition&);
276
277
OMNI_THREAD_EXPOSE:
278
OMNI_CONDITION_IMPLEMENTATION
279
};
280
281
282
///////////////////////////////////////////////////////////////////////////
283
//
284
// Counting semaphore
285
//
286
///////////////////////////////////////////////////////////////////////////
287
288
class _OMNITHREAD_NTDLL_ omni_semaphore {
289
290
public:
291
omni_semaphore(unsigned int initial = 1);
292
~omni_semaphore(void);
293
294
void wait(void);
295
// if semaphore value is > 0 then decrement it and carry on. If it's
296
// already 0 then block.
297
298
int trywait(void);
299
// if semaphore value is > 0 then decrement it and return 1 (true).
300
// If it's already 0 then return 0 (false).
301
302
void post(void);
303
// if any threads are blocked in wait(), wake one of them up. Otherwise
304
// increment the value of the semaphore.
305
306
private:
307
// dummy copy constructor and operator= to prevent copying
308
omni_semaphore(const omni_semaphore&);
309
omni_semaphore& operator=(const omni_semaphore&);
310
311
OMNI_THREAD_EXPOSE:
312
OMNI_SEMAPHORE_IMPLEMENTATION
313
};
314
315
//
316
// A helper class for semaphores, similar to omni_mutex_lock above.
317
//
318
319
class _OMNITHREAD_NTDLL_ omni_semaphore_lock {
320
omni_semaphore& sem;
321
public:
322
omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); }
323
~omni_semaphore_lock(void) { sem.post(); }
324
private:
325
// dummy copy constructor and operator= to prevent copying
326
omni_semaphore_lock(const omni_semaphore_lock&);
327
omni_semaphore_lock& operator=(const omni_semaphore_lock&);
328
};
329
330
331
///////////////////////////////////////////////////////////////////////////
332
//
333
// Thread
334
//
335
///////////////////////////////////////////////////////////////////////////
336
337
class _OMNITHREAD_NTDLL_ omni_thread {
338
339
public:
340
341
enum priority_t {
342
PRIORITY_LOW,
343
PRIORITY_NORMAL,
344
PRIORITY_HIGH
345
};
346
347
enum state_t {
348
STATE_NEW, // thread object exists but thread hasn't
349
// started yet.
350
STATE_RUNNING, // thread is running.
351
STATE_TERMINATED // thread has terminated but storage has not
352
// been reclaimed (i.e. waiting to be joined).
353
};
354
355
//
356
// Constructors set up the thread object but the thread won't start until
357
// start() is called. The create method can be used to construct and start
358
// a thread in a single call.
359
//
360
361
omni_thread(void (*fn)(void*), void* arg = NULL,
362
priority_t pri = PRIORITY_NORMAL);
363
omni_thread(void* (*fn)(void*), void* arg = NULL,
364
priority_t pri = PRIORITY_NORMAL);
365
// these constructors create a thread which will run the given function
366
// when start() is called. The thread will be detached if given a
367
// function with void return type, undetached if given a function
368
// returning void*. If a thread is detached, storage for the thread is
369
// reclaimed automatically on termination. Only an undetached thread
370
// can be joined.
371
372
void start(void);
373
// start() causes a thread created with one of the constructors to
374
// start executing the appropriate function.
375
376
protected:
377
378
omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL);
379
// this constructor is used in a derived class. The thread will
380
// execute the run() or run_undetached() member functions depending on
381
// whether start() or start_undetached() is called respectively.
382
383
void start_undetached(void);
384
// can be used with the above constructor in a derived class to cause
385
// the thread to be undetached. In this case the thread executes the
386
// run_undetached member function.
387
388
virtual ~omni_thread(void);
389
// destructor cannot be called by user (except via a derived class).
390
// Use exit() or cancel() instead. This also means a thread object must
391
// be allocated with new - it cannot be statically or automatically
392
// allocated. The destructor of a class that inherits from omni_thread
393
// shouldn't be public either (otherwise the thread object can be
394
// destroyed while the underlying thread is still running).
395
396
public:
397
398
void join(void**);
399
// join causes the calling thread to wait for another's completion,
400
// putting the return value in the variable of type void* whose address
401
// is given (unless passed a null pointer). Only undetached threads
402
// may be joined. Storage for the thread will be reclaimed.
403
404
void set_priority(priority_t);
405
// set the priority of the thread.
406
407
static omni_thread* create(void (*fn)(void*), void* arg = NULL,
408
priority_t pri = PRIORITY_NORMAL);
409
static omni_thread* create(void* (*fn)(void*), void* arg = NULL,
410
priority_t pri = PRIORITY_NORMAL);
411
// create spawns a new thread executing the given function with the
412
// given argument at the given priority. Returns a pointer to the
413
// thread object. It simply constructs a new thread object then calls
414
// start.
415
416
static void exit(void* return_value = NULL);
417
// causes the calling thread to terminate.
418
419
static omni_thread* self(void);
420
// returns the calling thread's omni_thread object.
421
// If the calling thread is not the main thread and
422
// is not created using this library, returns 0.
423
424
static void yield(void);
425
// allows another thread to run.
426
427
static void sleep(unsigned long secs, unsigned long nanosecs = 0);
428
// sleeps for the given time.
429
430
static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
431
unsigned long rel_sec = 0, unsigned long rel_nsec=0);
432
// calculates an absolute time in seconds and nanoseconds, suitable for
433
// use in timed_waits on condition variables, which is the current time
434
// plus the given relative offset.
435
436
private:
437
438
virtual void run(void* arg) {}
439
virtual void* run_undetached(void* arg) { return NULL; }
440
// can be overridden in a derived class. When constructed using the
441
// the constructor omni_thread(void*, priority_t), these functions are
442
// called by start() and start_undetached() respectively.
443
444
void common_constructor(void* arg, priority_t pri, int det);
445
// implements the common parts of the constructors.
446
447
omni_mutex mutex;
448
// used to protect any members which can change after construction,
449
// i.e. the following 2 members:
450
451
state_t _state;
452
priority_t _priority;
453
454
static omni_mutex* next_id_mutex;
455
static int next_id;
456
int _id;
457
458
void (*fn_void)(void*);
459
void* (*fn_ret)(void*);
460
void* thread_arg;
461
int detached;
462
463
public:
464
465
priority_t priority(void) {
466
467
// return this thread's priority.
468
469
omni_mutex_lock l(mutex);
470
return _priority;
471
}
472
473
state_t state(void) {
474
475
// return thread state (invalid, new, running or terminated).
476
477
omni_mutex_lock l(mutex);
478
return _state;
479
}
480
481
int id(void) { return _id; }
482
// return unique thread id within the current process.
483
484
485
// This class plus the instance of it declared below allows us to execute
486
// some initialisation code before main() is called.
487
488
class _OMNITHREAD_NTDLL_ init_t {
489
static int count;
490
public:
491
init_t(void);
492
};
493
494
friend class init_t;
495
496
OMNI_THREAD_EXPOSE:
497
OMNI_THREAD_IMPLEMENTATION
498
};
499
500
static omni_thread::init_t omni_thread_init;
501
502
#endif
503
504