summaryrefslogtreecommitdiff
path: root/graphtft-fe/thread.h
blob: e40d2221efc0b7f07f4e7a28fa5825665da6e484 (plain)
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
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * 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.0 2007/02/24 16:13:28 kls Exp $
 */

#ifndef __MYTHREAD_H
#define __MYTHREAD_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.
      ///< \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.
};

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 cMyThread {
  friend class cMyThreadLock;
private:
  bool active;
  bool running;
  pthread_t childTid;
  tThreadId childThreadId;
  cMutex mutex;
  char *description;
  static tThreadId mainThreadId;
  static void *StartThread(cMyThread *Thread);
protected:
  void SetPriority(int Priority);
  void Lock(void) { mutex.Lock(); }
  void Unlock(void) { mutex.Unlock(); }
  virtual void Action(void) = 0;
       ///< A derived cMyThread 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 cMyThread 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:
  cMyThread(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.
  virtual ~cMyThread();
  void SetDescription(const char *Description);
  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);
  };

// cMyThreadLock 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
// cMyThreadLock may itself use a cMyThreadLock to make one longer lock instead of many
// short ones.

class cMyThreadLock {
private:
  cMyThread *thread;
  bool locked;
public:
  cMyThreadLock(cMyThread *Thread = NULL);
  ~cMyThreadLock();
  bool Lock(cMyThread *Thread);
  };

//#define LOCK_THREAD cMyThreadLock ThreadLock(this)

#endif //__MYTHREAD_H