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
|
/**
* File: Thread.h
* Project: libvdr - classes taken from vdr-project
*
* from "Video Disk Recorder":
*
* Copyright (C) 2000, 2003, 2006, 2008 Klaus Schmidinger
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* The original author can be reached at kls@tvdr.de
*
* The vdr project's page is at http://www.tvdr.de
*
* ++2012-07-04(rma):
* As I don't like the necessity to subclass what should work in a thread,
* I extended the original sources, so that an arbitrary function can be
* a thread kernel.
*/
#ifndef THREAD_H
#define THREAD_H
#include <Mutex.h>
#include <stddef.h>
#include <pthread.h>
typedef pid_t tThreadId;
class cThread {
public:
cThread(const char *Description = NULL);
///< Creates a new thread.
///< If Description is present, a log file entry will be made when
///< the thread starts and stops. The Start() function must be called
///< to actually start the thread.
cThread(int (*ThreadCallback)(void *opaque, cThread *instance), void *opaque, const char *Description = NULL);
virtual ~cThread();
void SetDescription(const char *Description, ...) __attribute__ ((format (printf, 2, 3)));
bool Start(void);
///< Actually starts the thread.
///< If the thread is already running, nothing happens.
virtual void Cancel(int WaitSeconds = 0);
///< Cancels the thread by first setting 'running' to false, so that
///< the Action() loop can finish in an orderly fashion and then waiting
///< up to WaitSeconds seconds for the thread to actually end. If the
///< thread doesn't end by itself, it is killed.
///< If WaitSeconds is -1, only 'running' is set to false and Cancel()
///< returns immediately, without killing the thread.
bool Active(void);
///< used from outside to check whether the thread is still alive.
bool Running(void) { return running; }
///< used from inside the thread to check whether it may keep on running.
///< Returns false if a derived cThread object shall leave its Action()
///< function. Should be public and so available for callback thread kernels
static tThreadId ThreadId(void);
static tThreadId IsMainThread(void) { return ThreadId() == mainThreadId; }
static void SetMainThreadId(void);
protected:
void SetPriority(int Priority);
void SetIOPriority(int Priority);
void Lock(void) { mutex.Lock(); }
void Unlock(void) { mutex.Unlock(); }
virtual void Action(void);
///< A derived cThread class must implement the code it wants to
///< execute as a separate thread in this function. If this is
///< a loop, it must check Running() repeatedly to see whether
///< it's time to stop.
///< To support callbacks as thread kernels, default implementation now
///< starts the callback
private:
bool active;
bool running;
pthread_t childTid;
tThreadId childThreadId;
cMutex mutex;
char *description;
int (*threadCallback)(void *, cThread *);
void *opaque;
static tThreadId mainThreadId;
static void *StartThread(cThread *Thread);
friend class cThreadLock;
};
#endif /* THREAD_H */
|