2000-10-08 09:25:20 +02:00
|
|
|
/*
|
|
|
|
* thread.h: A simple thread base class
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2005-12-11 12:10:28 +01:00
|
|
|
* $Id: thread.h 1.33 2005/12/11 12:04:56 kls Exp $
|
2000-10-08 09:25:20 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __THREAD_H
|
|
|
|
#define __THREAD_H
|
|
|
|
|
|
|
|
#include <pthread.h>
|
2001-09-15 13:00:58 +02:00
|
|
|
#include <stdio.h>
|
2000-10-08 09:25:20 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
2004-10-16 09:36:28 +02:00
|
|
|
class cCondWait {
|
|
|
|
private:
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
pthread_cond_t cond;
|
|
|
|
bool signaled;
|
|
|
|
public:
|
|
|
|
cCondWait(void);
|
|
|
|
~cCondWait();
|
2004-10-24 11:12:05 +02:00
|
|
|
static void SleepMs(int TimeoutMs);
|
|
|
|
///< Creates a cCondWait object and uses it to sleep for TimeoutMs
|
|
|
|
///< milliseconds, immediately giving up the calling thread's time
|
|
|
|
///< slice and thus avoiding a "busy wait".
|
2005-01-14 14:08:47 +01:00
|
|
|
///< In order to avoid a possible busy wait, TimeoutMs will be automatically
|
|
|
|
///< limited to values >2.
|
2004-10-16 09:36:28 +02:00
|
|
|
bool Wait(int TimeoutMs = 0);
|
|
|
|
///< Waits at most TimeoutMs milliseconds for a call to Signal(), or
|
|
|
|
///< forever if TimeoutMs is 0.
|
|
|
|
///< \return Returns true if Signal() has been called, false it the given
|
|
|
|
///< timeout has expired.
|
|
|
|
void Signal(void);
|
|
|
|
///< Signals a caller of Wait() that the condition it is waiting for is met.
|
|
|
|
};
|
|
|
|
|
2001-08-03 14:18:08 +02:00
|
|
|
class cMutex;
|
|
|
|
|
|
|
|
class cCondVar {
|
|
|
|
private:
|
|
|
|
pthread_cond_t cond;
|
|
|
|
public:
|
|
|
|
cCondVar(void);
|
|
|
|
~cCondVar();
|
2002-08-15 11:46:22 +02:00
|
|
|
void Wait(cMutex &Mutex);
|
|
|
|
bool TimedWait(cMutex &Mutex, int TimeoutMs);
|
2001-08-03 14:18:08 +02:00
|
|
|
void Broadcast(void);
|
|
|
|
};
|
|
|
|
|
2004-01-04 12:30:00 +01:00
|
|
|
class cRwLock {
|
2003-12-22 13:29:24 +01:00
|
|
|
private:
|
|
|
|
pthread_rwlock_t rwlock;
|
|
|
|
public:
|
2004-01-04 12:30:00 +01:00
|
|
|
cRwLock(bool PreferWriter = false);
|
|
|
|
~cRwLock();
|
2003-12-22 13:29:24 +01:00
|
|
|
bool Lock(bool Write, int TimeoutMs = 0);
|
|
|
|
void Unlock(void);
|
|
|
|
};
|
|
|
|
|
2000-11-18 13:57:32 +01:00
|
|
|
class cMutex {
|
2001-08-03 14:18:08 +02:00
|
|
|
friend class cCondVar;
|
2000-11-18 13:57:32 +01:00
|
|
|
private:
|
|
|
|
pthread_mutex_t mutex;
|
2001-06-02 10:47:40 +02:00
|
|
|
int locked;
|
2000-11-18 13:57:32 +01:00
|
|
|
public:
|
2001-06-02 10:47:40 +02:00
|
|
|
cMutex(void);
|
|
|
|
~cMutex();
|
|
|
|
void Lock(void);
|
|
|
|
void Unlock(void);
|
2000-11-18 13:57:32 +01:00
|
|
|
};
|
|
|
|
|
2005-12-11 12:10:28 +01:00
|
|
|
typedef pid_t tThreadId;
|
2005-11-27 15:57:03 +01:00
|
|
|
|
2000-10-08 09:25:20 +02:00
|
|
|
class cThread {
|
|
|
|
friend class cThreadLock;
|
|
|
|
private:
|
2005-08-13 13:17:24 +02:00
|
|
|
bool active;
|
2005-08-14 11:24:57 +02:00
|
|
|
bool running;
|
2004-12-19 10:58:20 +01:00
|
|
|
pthread_t childTid;
|
2001-10-27 13:23:06 +02:00
|
|
|
cMutex mutex;
|
2003-10-18 12:29:08 +02:00
|
|
|
char *description;
|
2005-11-27 15:57:03 +01:00
|
|
|
static tThreadId mainThreadId;
|
2001-06-02 10:47:40 +02:00
|
|
|
static bool emergencyExitRequested;
|
2000-10-08 09:25:20 +02:00
|
|
|
static void *StartThread(cThread *Thread);
|
2002-06-16 12:57:31 +02:00
|
|
|
protected:
|
2005-05-29 11:44:52 +02:00
|
|
|
void SetPriority(int Priority);
|
2001-10-27 13:23:06 +02:00
|
|
|
void Lock(void) { mutex.Lock(); }
|
|
|
|
void Unlock(void) { mutex.Unlock(); }
|
2000-10-08 09:25:20 +02:00
|
|
|
virtual void Action(void) = 0;
|
2005-08-13 13:17:24 +02:00
|
|
|
///< A derived cThread class must implement the code it wants to
|
|
|
|
///< execute as a separate thread in this function. If this is
|
2005-08-14 11:24:57 +02:00
|
|
|
///< a loop, it must check Running() repeatedly to see whether
|
2005-08-13 13:17:24 +02:00
|
|
|
///< it's time to stop.
|
2005-08-14 11:24:57 +02:00
|
|
|
bool Running(void) { return running; }
|
2005-08-13 13:17:24 +02:00
|
|
|
///< Returns false if a derived cThread object shall leave its Action()
|
|
|
|
///< function.
|
2000-12-08 16:23:32 +01:00
|
|
|
void Cancel(int WaitSeconds = 0);
|
2005-08-14 11:24:57 +02:00
|
|
|
///< Cancels the thread by first setting 'running' to false, so that
|
2005-08-13 13:17:24 +02:00
|
|
|
///< 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.
|
2000-10-08 09:25:20 +02:00
|
|
|
public:
|
2003-10-18 12:29:08 +02:00
|
|
|
cThread(const char *Description = NULL);
|
2005-08-13 13:17:24 +02:00
|
|
|
///< 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.
|
2000-10-08 09:25:20 +02:00
|
|
|
virtual ~cThread();
|
2005-10-09 11:14:14 +02:00
|
|
|
void SetDescription(const char *Description, ...) __attribute__ ((format (printf, 2, 3)));
|
2000-10-08 09:25:20 +02:00
|
|
|
bool Start(void);
|
2005-08-13 13:17:24 +02:00
|
|
|
///< Actually starts the thread.
|
2005-08-14 11:24:57 +02:00
|
|
|
bool Active(void);
|
|
|
|
///< Checks whether the thread is still alive.
|
2001-06-02 10:47:40 +02:00
|
|
|
static bool EmergencyExit(bool Request = false);
|
2005-12-11 12:10:28 +01:00
|
|
|
static tThreadId ThreadId(void);
|
2005-11-27 15:57:03 +01:00
|
|
|
static tThreadId IsMainThread(void) { return ThreadId() == mainThreadId; }
|
2000-10-08 09:25:20 +02:00
|
|
|
};
|
2002-02-23 13:55:57 +01:00
|
|
|
|
|
|
|
// cMutexLock can be used to easily set a lock on mutex and make absolutely
|
|
|
|
// sure that it will be unlocked when the block will be left. Several locks can
|
|
|
|
// be stacked, so a function that makes many calls to another function which uses
|
|
|
|
// cMutexLock may itself use a cMutexLock to make one longer lock instead of many
|
|
|
|
// short ones.
|
|
|
|
|
|
|
|
class cMutexLock {
|
|
|
|
private:
|
|
|
|
cMutex *mutex;
|
|
|
|
bool locked;
|
|
|
|
public:
|
|
|
|
cMutexLock(cMutex *Mutex = NULL);
|
|
|
|
~cMutexLock();
|
|
|
|
bool Lock(cMutex *Mutex);
|
|
|
|
};
|
2000-10-08 09:25:20 +02:00
|
|
|
|
|
|
|
// cThreadLock can be used to easily set a lock in a thread and make absolutely
|
|
|
|
// sure that it will be unlocked when the block will be left. Several locks can
|
|
|
|
// be stacked, so a function that makes many calls to another function which uses
|
|
|
|
// cThreadLock may itself use a cThreadLock to make one longer lock instead of many
|
|
|
|
// short ones.
|
|
|
|
|
|
|
|
class cThreadLock {
|
|
|
|
private:
|
|
|
|
cThread *thread;
|
|
|
|
bool locked;
|
|
|
|
public:
|
2000-10-29 13:17:22 +01:00
|
|
|
cThreadLock(cThread *Thread = NULL);
|
2000-10-08 09:25:20 +02:00
|
|
|
~cThreadLock();
|
2000-10-29 13:17:22 +01:00
|
|
|
bool Lock(cThread *Thread);
|
2000-10-08 09:25:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define LOCK_THREAD cThreadLock ThreadLock(this)
|
|
|
|
|
2001-09-15 13:00:58 +02:00
|
|
|
// cPipe implements a pipe that closes all unnecessary file descriptors in
|
|
|
|
// the child process.
|
|
|
|
|
|
|
|
class cPipe {
|
|
|
|
private:
|
|
|
|
pid_t pid;
|
|
|
|
FILE *f;
|
|
|
|
public:
|
|
|
|
cPipe(void);
|
|
|
|
~cPipe();
|
|
|
|
operator FILE* () { return f; }
|
|
|
|
bool Open(const char *Command, const char *Mode);
|
|
|
|
int Close(void);
|
|
|
|
};
|
|
|
|
|
2001-10-20 10:39:27 +02:00
|
|
|
// SystemExec() implements a 'system()' call that closes all unnecessary file
|
|
|
|
// descriptors in the child process.
|
|
|
|
|
|
|
|
int SystemExec(const char *Command);
|
|
|
|
|
2000-10-08 09:25:20 +02:00
|
|
|
#endif //__THREAD_H
|