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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* Copyright (C) 2007-2023 Xagasoft, All rights reserved.
*
* This file is part of the libbu++ library and is released under the
* terms of the license contained in the file LICENSE.
*/
#ifndef BU_THREAD_H
#define BU_THREAD_H
#include "bu/config.h"
#include <pthread.h>
#include "bu/exceptionbase.h"
namespace Bu
{
subExceptionDecl( ThreadException );
class ThreadId
{
friend class Thread;
private:
ThreadId( pthread_t tId );
public:
ThreadId();
bool operator==( const ThreadId &rhs );
bool operator!=( const ThreadId &rhs );
pthread_t getId() const { return tId; }
private:
pthread_t tId;
};
/**
* Simple thread class. This wraps the basic pthread (posix threads)
* system in an object oriented sort of way. It allows you to create a
* class with standard member variables and callable functions that can be
* run in it's own thread, one per class instance.
*@ingroup Threading
*/
class Thread
{
public:
/**
* Construct an Thread thread.
*/
Thread();
/**
* Destroy an Thread thread.
*/
virtual ~Thread();
static ThreadId currentThread();
ThreadId getId() { return ThreadId( ptHandle ); }
/**
* Begin thread execution. This will call the overridden run function,
* which will simply execute in it's own thread until the function
* exits, the thread is killed, or the thread is cancelled (optionally).
* The thread started in this manner has access to all of it's class
* variables, but be sure to protect possible multiple-access with
* ThreadMutex objects.
* @returns True if starting the thread was successful. False if
* something went wrong and the thread has not started.
*/
bool start();
/**
* Forcibly kill a thread. This is not generally considered a good
* thing to do, but in those rare cases you need it, it's invaluable.
* The problem with stopping (or killing) a thread is that it stops it
* the moment you call stop, no matter what it's doing. The object
* oriented approach to this will help clean up any class variables
* that were used, but anything not managed as a member variable will
* probably create a memory leak type of situation. Instead of stop,
* consider using cancel, which can be handled by the running thread in
* a graceful manner.
*
* NOTE: This was called stop(), but that was too ambiguous and common
* of a name to implement in subclasses. The functionality was not
* obvious, and this was sometimes used in place of a clean stopping
* routine.
*@returns True if the thread was stopped, false otherwise. When this
* function returns the thread may not have stopped, to ensure that the
* thread has really stopped, call join.
*/
bool forceStop();
/**
* Join the thread in action. This function performs what is commonly
* called a thread join. That is that it effectively makes the calling
* thread an the Thread thread contained in the called object one in the
* same, and pauses the calling thread until the called thread exits.
* That is, when called from, say, your main(), mythread.join() will
* not return until the thread mythread has exited. This is very handy
* at the end of programs to ensure all of your data was cleaned up.
*@returns True if the thread was joined, false if the thread couldn't
* be joined, usually because it isn't running to begin with.
*/
bool join();
private:
pthread_t ptHandle; /**< Internal handle to the posix thread. */
protected:
/**
* The workhorse of the Thread class. This is the function that will
* run in the thread, when this function exits the thread dies and is
* cleaned up by the system. Make sure to read up on Bu::Mutex,
* Bu::Condition, and the Bu::Synchro* classes to see how to control
* and protect everything you do in a safe way within this function.
*@returns I'm not sure right now, but this is the posix standard form.
*/
virtual void run()=0;
/**
* Gives up some cpu-time in the currently running thread. If a thread
* is working hard, but you want to give other threads on the system
* some time to do some work, call yield.
*/
void yield();
/**
* Sets the name of the thread. The sName parameter must be a C string
* with a max length of 16 bytes including null terminator.
*/
void setName( const char *sName );
private:
/**
* This is the hidden-heart of the thread system. While run is what the
* user gets to override, and everything said about it is true, this is
* the function that actually makes up the thread, it simply calls the
* run member function in an OO-friendly way. This is what allows us to
* use member variables from within the thread itself.
*@param pThread Should always be this.
*@returns This is specified by posix, I'm not sure yet.
*/
static void *threadRunner( void *pThread );
};
}
#endif
|