vdr/thread.h
Klaus Schmidinger 4c59501a6b Version 1.7.38
VDR developer version 1.7.38 is now available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.38.tar.bz2

A 'diff' against the previous version is available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.37-1.7.38.diff

MD5 checksums:

f4ef0f60ed662f3c983a830da67df9b2  vdr-1.7.38.tar.bz2
e945b0f44e13ed768de726cf6e66317c  vdr-1.7.37-1.7.38.diff

WARNING:
========

This is a developer version. Even though I use it in my productive
environment. I strongly recommend that you only use it under controlled
conditions and for testing and debugging.

Approaching version 2.0.0:
==========================

If all goes well, there should be no more functional or API changes
before the final version 2.0.0. There will just be a few more fixes.

From the HISTORY file:
- Updated the Ukrainian OSD texts (thanks to Yarema Aka Knedlyk).
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
- Updated the Romanian OSD texts (thanks to Lucian Muresan).
- Updated the French OSD texts (thanks to Marc Perrudin, Bernard Jaulini and Peter
  Münster).
- Updated the Macedonian OSD texts (thanks to Dimitar Petrovski).
- Fixed moving editing marks, so that they don't get overwritten with old values
  through an update of the marks file.
- Removed an invalid line from channels.conf.terr (reported by Lars Hanisch).
- Fixed an unexpected k_Repeat key event after a k_Release in lirc.c.
- Fixed permissions of po/sr_SR.po (reported by Dominic Evans).
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- Fixed using "Pause" and "Slow motion" near the end of a recording (replay stopped
  a few seconds after the end of the recording file has been reached).
- Fixed selecting the last replayed recording in the Recordings menu in case there
  are folders and plain recordings with names that differ only in non-alphanumeric
  characters (reported by Andre Weidemann).
- Fixed the description of the OSD drawing functions DrawEllipse() (the values -5...-8
  for the Quadrants parameter are not implemented).
- Made cOsd::DestroyPixmap() "NULL proof".
- Now deleting any previously allocated pixmaps in cOsd::SetAreas().
- Added demos of the DrawEllipse() and DrawSlope() function to the 'osddemo'
  plugin (press '1' or '2', respectively).
- Updated the Lithuanian OSD texts (thanks to Valdemaras Pipiras).
- The timeout for trying to switch to a valid programme is now reset immediately once
  a programme has been found.
- No longer checking for EOPNOTSUPP in cDvbTuner::GetSignalQuality() to avoid breaking
  this function in case the driver suddenly decides to return a different errno value
  if an operation is not supported.
- Moved the definition of TIMERMACRO_TITLE and TIMERMACRO_EPISODE from recording.h to
  config.h and using them to initialize Setup.NameInstantRecord (avoids having the same
  information in two places).
- Fixed the return value of cOsdProvider::StoreImage() in case there is no OSD provider.
- Fixed a crash in cMenuEditChanItem::Set() when entering a channel number that
  doesn't exist (reported by Mikael Hübsch).
- Fixed displaying pending timers in "alert" mode in the LCARS skin.
- Added missing $(LDFLAGS) to the Makefile of the dvbhddevice plugin (thanks to Ville
  Skyttä).
- Fixed some spellings in PLUGINS.html and Doxyfile (thanks to Ville Skyttä).
- Added '-p' to the cp command in the install-conf target of the Makefile (thanks to
  Ville Skyttä).
- Added missing 'const' to cDevice::HasProgramme() and cDevice::HasLock().
- Fixed determining the priority of the primary device in case it is neither replaying
  nor receiving a live channel (thanks to Matthias Senzel for reporting a problem with
  switching back to live viewing after replay in a setup with device bonding).
- Removed all \return and \param tags from comment lines marked with "///<" for Doxygen.
  There was only a rather small number of these, and I would probably always forget to
  put them in place when writing future comments, so I decided to drop them entirely.
- Added Doxyfile.filter to have special characters escaped that would otherwise be
  dropped by Doxygen (reported by Ville Skyttä).
- Using 'cat' instead of 'cp' to copy the Doxyfile to avoid problems in case Doxyfile
  is write protected.
- Updated the Doxyfile with a newer version of Doxygen.
- Turned off following symlinks in the Doxyfile.
- Removed trailing whitespace.
- Expanded tabs in PLUGINS/src/dvbhddevice/setup.c.
- Some formatting fixes.
2013-02-17 18:11:16 +01:00

209 lines
6.2 KiB
C++

/*
* thread.h: A simple thread base class
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.h 2.4 2013/02/16 15:20:44 kls Exp $
*/
#ifndef __THREAD_H
#define __THREAD_H
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
class cCondWait {
private:
pthread_mutex_t mutex;
pthread_cond_t cond;
bool signaled;
public:
cCondWait(void);
~cCondWait();
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".
///< In order to avoid a possible busy wait, TimeoutMs will be automatically
///< limited to values >2.
bool Wait(int TimeoutMs = 0);
///< Waits at most TimeoutMs milliseconds for a call to Signal(), or
///< forever if TimeoutMs is 0.
///< 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.
};
class cMutex;
class cCondVar {
private:
pthread_cond_t cond;
public:
cCondVar(void);
~cCondVar();
void Wait(cMutex &Mutex);
bool TimedWait(cMutex &Mutex, int TimeoutMs);
void Broadcast(void);
};
class cRwLock {
private:
pthread_rwlock_t rwlock;
public:
cRwLock(bool PreferWriter = false);
~cRwLock();
bool Lock(bool Write, int TimeoutMs = 0);
void Unlock(void);
};
class cMutex {
friend class cCondVar;
private:
pthread_mutex_t mutex;
int locked;
public:
cMutex(void);
~cMutex();
void Lock(void);
void Unlock(void);
};
typedef pid_t tThreadId;
class cThread {
friend class cThreadLock;
private:
bool active;
bool running;
pthread_t childTid;
tThreadId childThreadId;
cMutex mutex;
char *description;
bool lowPriority;
static tThreadId mainThreadId;
static void *StartThread(cThread *Thread);
protected:
void SetPriority(int Priority);
void SetIOPriority(int Priority);
void Lock(void) { mutex.Lock(); }
void Unlock(void) { mutex.Unlock(); }
virtual void Action(void) = 0;
///< 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.
bool Running(void) { return running; }
///< Returns false if a derived cThread object shall leave its Action()
///< function.
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.
public:
cThread(const char *Description = NULL, bool LowPriority = false);
///< 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.
///< LowPriority can be set to true to make this thread run at a lower
///< priority.
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.
bool Active(void);
///< Checks whether the thread is still alive.
static tThreadId ThreadId(void);
static tThreadId IsMainThread(void) { return ThreadId() == mainThreadId; }
static void SetMainThreadId(void);
};
// 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);
};
// 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:
cThreadLock(cThread *Thread = NULL);
~cThreadLock();
bool Lock(cThread *Thread);
};
#define LOCK_THREAD cThreadLock ThreadLock(this)
class cIoThrottle {
private:
static cMutex mutex;
static int count;
bool active;
public:
cIoThrottle(void);
~cIoThrottle();
void Activate(void);
///< Activates the global I/O throttling mechanism.
///< This function may be called any number of times, but only
///< the first call after an inactive state will have an effect.
void Release(void);
///< Releases the global I/O throttling mechanism.
///< This function may be called any number of times, but only
///< the first call after an active state will have an effect.
bool Active(void) { return active; }
///< Returns true if this I/O throttling object is currently active.
static bool Engaged(void);
///< Returns true if any I/O throttling object is currently active.
};
// 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);
};
// SystemExec() implements a 'system()' call that closes all unnecessary file
// descriptors in the child process.
// With Detached=true, calls command in background and in a separate session,
// with stdin connected to /dev/null.
int SystemExec(const char *Command, bool Detached = false);
#endif //__THREAD_H