Newer
Older
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
#ifndef THREADABLE_H
#define THREADABLE_H 1
/*
* Generic class for something readable by a threaded assistant
*/
#include <pthread.h>
template <class T> class Threader {
private:
bool threaded_; // is a separate reader thread running?
pthread_t th_;
pthread_mutex_t mut_; // lock on shared data
char *name_;
public:
Threader() : threaded_(false), name_(NULL)
{
pthread_mutex_init( &mut_, NULL );
}
class Thunk {
void *(T::*func_)(void);
T *inst_;
// private constructor -- thanks to Matt Hall
Thunk( T *inst, void *(T::*func)() ) : inst_(inst), func_(func)
{ }
public:
static Thunk *make( T *inst, void *(T::*func)(void) ) {
return new Thunk( inst, func );
}
static void *call( Thunk *deleteme ) {
Thunk t = *deleteme;
delete deleteme;
return ((t.inst_)->*(t.func_))();
}
};
public:
void start( T *inst, void *(T::*func)(void) ) {
threaded_ = true;
Thunk *g = Thunk::make( inst, func );
pthread_create( &th_, NULL, (void *(*)(void *))&g->call, (void *)g );
}
pthread_mutex_t &mutex() { return mut_; }
bool threading() const { return threaded_; }
void lock() {
if(threaded_) {
if(pthread_mutex_lock( &mut_ ) != 0) {
fprintf(stderr, "%s->lock(): %s\n",
name_ ? name_ : "Threader", strerror(errno));
}
}
}
void unlock() {
if(threaded_) {
if(pthread_mutex_unlock( &mut_ ) != 0) {
fprintf(stderr, "%s->unlock(): %s\n",
name_ ? name_ : "Threader", strerror(errno));
}
}
}
void testcancel() {
if(threaded_) pthread_testcancel();
}
void cancel() {
if(threaded_) {
if(pthread_cancel( th_ ) != 0) {
fprintf(stderr, "%s->cancel(0x%lx): %s\n",
name_ ? name_ : "Threadable",
(long int)th_, strerror(errno));
}
}
}
};
// Maybe convenient for above?
// { scoped_lock lock(threader.mutex());
// mess with threader's contents
// }
class scoped_lock {
pthread_mutex_t *m_;
public:
scoped_lock( pthread_mutex_t &mut ) {
m_ = &mut;
pthread_mutex_lock( m_ );
}
~scoped_lock() {
pthread_mutex_unlock( m_ );
}
};
#endif /*THREADABLE_H*/