r42@gandalf: fugalh | 2006-06-07 17:08:39 -0600
[ardour.git] / libs / pbd3 / pbd / thread.h
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #ifndef __qm_thread_h__
22 #define __qm_thread_h__
23
24 #include <pthread.h>
25
26 /* A generic base class for Quasimodo objects requiring their own
27    thread to do work.
28 */
29
30 class QMThread 
31
32 {
33  public:
34         QMThread (const char *name, 
35                   void *(start)(void *), void *, 
36                   bool realtime = false, int rt_priority = 10);
37
38         virtual ~QMThread();
39
40         int   run ();
41         void  poke ();
42         void  pause ();
43         void  stop ();
44         void  *wait ();
45
46         /* This doesn't guarantee anything about the state of
47            the thread, but if you do things the right way, and
48            make sure that the do_work() routine checks 
49            work_no_more() at the right times, and that the
50            thread is awake, then calling this will cause
51            the thread to exit fairly quickly.
52         */
53
54         void  halt() { _must_exit = true ; }
55
56         void  exit (void *status);
57         pthread_t thread_id() { return _thread; }
58
59         bool thread_ok () { return _have_thread; }
60         bool thread_active() { return _thread_active; }
61
62         bool thread_running () {
63                 /* XXX not atomic */
64                 return _running && _thread_active;
65         }
66
67         bool thread_waiting () { return _thread_waiting; }
68
69         static void try_to_kill_all_threads() {
70                 all_threads_must_die = true;
71         }
72
73  protected:
74         void *main ();
75
76         bool  work_no_more () { return (!_running || _must_exit || all_threads_must_die); }
77
78         bool  myself () { 
79                 return pthread_equal (_thread, pthread_self());
80         }
81
82         void suspend() {
83                 _running = false;
84         }
85
86         void lock (pthread_mutex_t *lock) {
87                 pthread_mutex_lock (lock);
88         }
89         
90         void unlock (pthread_mutex_t *lock) {
91                 pthread_mutex_unlock (lock);
92         }
93
94         virtual void *do_work () = 0;
95
96   private:
97         const char *_name;
98         bool _must_exit;
99         bool _running;
100         bool _thread_active;
101         bool _thread_waiting;
102         bool _have_thread;
103
104         size_t work_cnt;
105
106         pthread_mutex_t status_lock;
107         pthread_cond_t wake_up; /* protected by status_lock */
108         pthread_cond_t asleep;  /* protected by status_lock */
109         pthread_cond_t running; /* protected by status_lock */
110         pthread_cond_t exited;  /* protected by status_lock */
111         pthread_t _thread;
112         
113         void lock () { 
114                 pthread_mutex_lock (&status_lock);
115         }
116
117         void unlock () { 
118                 pthread_mutex_unlock (&status_lock);
119         }
120
121         static bool all_threads_must_die;
122         
123         static void signal_catcher (int sig);
124         void setup_signals ();
125 };
126
127 #endif // __qm_thread_h__