forked from pixelb/libs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPadThreads.h
128 lines (105 loc) · 3.37 KB
/
PadThreads.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#ifndef PAD_THREADS_H
#define PAD_THREADS_H
// If GETOUT_CLAUSE is defined, a lock can only be refused for that number of seconds
//#define GETOUT_CLAUSE 5
#ifdef GETOUT_CLAUSE
static volatile int mutexCount = 0;
#include "tracer.h"
#endif //GETOUT_CLAUSE
// Number of MICROseconds between attempts to access a lock
#define LOCK_CHECK_DELAY (5000)
#ifdef WIN32
#include <cygnus\pthread.h>
#else
#include <pthread.h>
#endif /* WIN32 */
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <unistd.h>
class CriticalSection
{
public:
#ifdef GETOUT_CLAUSE //useful for debugging deadlocks
CriticalSection() {
pthread_mutex_init(&mutex, NULL);
// mutexNum = mutexCount++;
}
~CriticalSection() {
pthread_mutex_destroy(&mutex);
}
void enter(void){
int result;
int retryCount = 0;
while((result=pthread_mutex_trylock(&mutex)) != 0) {
//DebugMsg(0, "Lock = failed for pid %d - retrying\n", mutexNum, (int) getpid());
usleep(LOCK_CHECK_DELAY);
if ((GETOUT_CLAUSE * 1000000) <= (LOCK_CHECK_DELAY * ++retryCount)) {
DebugMsg(5, "Process %d failed to acquire lock %d - using GETOUT_CLAUSE\n", getpid(), mutexNum);
break;
}
}
//DebugMsg(0, "Lock = acquired by %d\n", mutexNum, (int) getpid());
}
void leave(void) {
pthread_mutex_unlock(&mutex);
//DebugMsg(0, "Lock = released by %d\n", mutexNum, (int) getpid());
}
#else
CriticalSection() {pthread_mutex_init (&mutex, NULL);}/*TODO: set attr for 1 process*/
~CriticalSection(){pthread_mutex_destroy(&mutex); }
void enter(void) {pthread_mutex_lock (&mutex); }/*TODO: return bool (false if EINVAL(mutex destroyed)), retry on EINTR?*/
void leave(void) {pthread_mutex_unlock (&mutex); }
pthread_mutex_t* pthread_mutex(void) { return &mutex; }
#endif
private:
pthread_mutex_t mutex;
// int mutexNum;
};
class rwlock
{
pthread_rwlock_t lock;
public:
rwlock() {pthread_rwlock_init(&lock, NULL);}
~rwlock() {pthread_rwlock_destroy(&lock);}
void readlock(void) {pthread_rwlock_rdlock(&lock);}
void writelock(void){pthread_rwlock_wrlock(&lock);}
void unlock(void) {pthread_rwlock_unlock(&lock);}
};
class Thread
{
public:
Thread();
virtual ~Thread();
bool StartThread(void);
bool StopThread(void);
bool PauseThread(void);
bool UnPauseThread(void);
void ExitIfNeeded(void);
bool fThreadRunning;
private:
pthread_t tid;
pthread_attr_t attr;
long ThreadParam;
/* This pure virtual function makes this class an ABC.
* I.E. this function must be implemented for each class
* that derives from this.
* Note that since the code in main will be running
* in a parallel thread of execution to everything else
* on the system it should release processing time when
* it's not doing anything useful. I.E. it should use
* the select(), sleep(), getMessage() calls etc. to yield
* the processor to the OS. An e.g. implementation of
* main could be:
*
* for(;;) {
* select(socket_descriptor); //Wait for data
* process(data);
* }
*/
virtual void main(void)=0;
//static member function means a global function,
//IE no this pointer is passed to it on the stack.
static void* ThreadStarter(void* lpParams);
};
#endif //PAD_THREADS_H