Imported Upstream version 3.0
[debian/gnuradio] / usrp / host / lib / mld_threads.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio.
6  *
7  * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
8  * 
9  * GNU Radio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  * 
14  * GNU Radio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with GNU Radio; see the file COPYING.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifndef _INCLUDED_MLD_THREADS_H_
26 #define _INCLUDED_MLD_THREADS_H_
27
28 /* classes which allow for either pthreads or omni_threads */
29
30 #ifdef _USE_OMNI_THREADS_
31 #include <gnuradio/omnithread.h>
32 #else
33 #include <pthread.h>
34 #endif
35
36 #include <stdexcept>
37
38 #define __INLINE__ inline
39
40 class mld_condition_t;
41
42 class mld_mutex_t {
43 #ifdef _USE_OMNI_THREADS_
44   typedef omni_mutex l_mutex, *l_mutex_ptr;
45 #else
46   typedef pthread_mutex_t l_mutex, *l_mutex_ptr;
47 #endif
48
49   friend class mld_condition_t;
50
51 private:
52   l_mutex_ptr d_mutex;
53
54 protected:
55   inline l_mutex_ptr mutex () { return (d_mutex); };
56
57 public:
58   __INLINE__ mld_mutex_t () {
59 #ifdef _USE_OMNI_THREADS_
60     d_mutex = new omni_mutex ();
61 #else
62     d_mutex = (l_mutex_ptr) new l_mutex;
63     int l_ret = pthread_mutex_init (d_mutex, NULL);
64     if (l_ret != 0) {
65       fprintf (stderr, "Error %d creating mutex.\n", l_ret);
66       throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n");
67     }
68 #endif
69   };
70
71   __INLINE__ ~mld_mutex_t () {
72     unlock ();
73 #ifndef _USE_OMNI_THREADS_
74     int l_ret = pthread_mutex_destroy (d_mutex);
75     if (l_ret != 0) {
76       fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): "
77                "Error %d destroying mutex.\n", l_ret);
78     }
79 #endif
80     delete d_mutex;
81     d_mutex = NULL;
82   };
83
84   __INLINE__ void lock () {
85 #ifdef _USE_OMNI_THREADS_
86     d_mutex->lock ();
87 #else
88     int l_ret = pthread_mutex_lock (d_mutex);
89     if (l_ret != 0) {
90       fprintf (stderr, "mld_mutex_t::lock(): "
91                "Error %d locking mutex.\n", l_ret);
92     }
93 #endif
94   };
95
96   __INLINE__ void unlock () {
97 #ifdef _USE_OMNI_THREADS_
98     d_mutex->unlock ();
99 #else
100     int l_ret = pthread_mutex_unlock (d_mutex);
101     if (l_ret != 0) {
102       fprintf (stderr, "mld_mutex_t::unlock(): "
103                "Error %d locking mutex.\n", l_ret);
104     }
105 #endif
106   };
107
108   __INLINE__ bool trylock () {
109 #ifdef _USE_OMNI_THREADS_
110     int l_ret = d_mutex->trylock ();
111 #else
112     int l_ret = pthread_mutex_unlock (d_mutex);
113 #endif
114     return (l_ret == 0 ? true : false);
115   };
116
117   inline void acquire () { lock(); };
118   inline void release () { unlock(); };
119   inline void wait () { lock(); };
120   inline void post () { unlock(); };
121 };
122
123 typedef mld_mutex_t mld_mutex, *mld_mutex_ptr;
124
125 class mld_condition_t {
126 #ifdef _USE_OMNI_THREADS_
127   typedef omni_condition l_condition, *l_condition_ptr;
128 #else
129   typedef pthread_cond_t l_condition, *l_condition_ptr;
130 #endif
131
132 private:
133   l_condition_ptr d_condition;
134   mld_mutex_ptr d_mutex;
135   bool d_waiting;
136
137 public:
138   __INLINE__ mld_condition_t () {
139     d_waiting = false;
140     d_mutex = new mld_mutex ();
141 #ifdef _USE_OMNI_THREADS_
142     d_condition = new omni_condition (d_mutex->mutex ());
143 #else
144     d_condition = (l_condition_ptr) new l_condition;
145     int l_ret = pthread_cond_init (d_condition, NULL);
146     if (l_ret != 0) {
147       fprintf (stderr, "Error %d creating condition.\n", l_ret);
148       throw std::runtime_error ("mld_condition_t::mld_condition_t()\n");
149     }
150 #endif
151   };
152
153   __INLINE__ ~mld_condition_t () {
154     signal ();
155 #ifndef _USE_OMNI_THREADS_
156     int l_ret = pthread_cond_destroy (d_condition);
157     if (l_ret != 0) {
158       fprintf (stderr, "mld_condition_t::mld_condition_t(): "
159                "Error %d destroying condition.\n", l_ret);
160     }
161 #endif
162     delete d_condition;
163     d_condition = NULL;
164     delete d_mutex;
165     d_mutex = NULL;
166   };
167
168   __INLINE__ void signal () {
169     if (d_waiting == true) {
170 #ifdef _USE_OMNI_THREADS_
171       d_condition->signal ();
172 #else
173       int l_ret = pthread_cond_signal (d_condition);
174       if (l_ret != 0) {
175         fprintf (stderr, "mld_condition_t::signal(): "
176                  "Error %d.\n", l_ret);
177       }
178 #endif
179       d_waiting = false;
180     }
181   };
182
183   __INLINE__ void wait () {
184     if (d_waiting == false) {
185       d_waiting = true;
186 #ifdef _USE_OMNI_THREADS_
187       d_condition->wait ();
188 #else
189       int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ());
190       if (l_ret != 0) {
191         fprintf (stderr, "mld_condition_t::wait(): "
192                  "Error %d.\n", l_ret);
193       }
194 #endif
195     }
196   };
197 };
198
199 typedef mld_condition_t mld_condition, *mld_condition_ptr;
200
201 class mld_thread_t {
202 #ifdef _USE_OMNI_THREADS_
203   typedef omni_thread l_thread, *l_thread_ptr;
204 #else
205   typedef pthread_t l_thread, *l_thread_ptr;
206 #endif
207
208 private:
209 #ifndef _USE_OMNI_THREADS_
210   l_thread d_thread;
211   void (*d_start_routine)(void*);
212   void *d_arg;
213 #else
214   l_thread_ptr d_thread;
215 #endif
216
217 #ifndef _USE_OMNI_THREADS_
218   static void* local_start_routine (void *arg) {
219     mld_thread_t* This = (mld_thread_t*) arg;
220     (*(This->d_start_routine))(This->d_arg);
221     return (NULL);
222   };
223 #endif
224
225 public:
226   __INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) {
227 #ifdef _USE_OMNI_THREADS_
228     d_thread = new omni_thread (start_routine, arg);
229     d_thread->start ();
230 #else
231     d_start_routine = start_routine;
232     d_arg = arg;
233     int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this);
234     if (l_ret != 0) {
235       fprintf (stderr, "Error %d creating thread.\n", l_ret);
236       throw std::runtime_error ("mld_thread_t::mld_thread_t()\n");
237     }
238 #endif
239   };
240
241   __INLINE__ ~mld_thread_t () {
242 #ifdef _USE_OMNI_THREADS_
243 //  delete d_thread;
244     d_thread = NULL;
245 #else
246     int l_ret = pthread_detach (d_thread);
247     if (l_ret != 0) {
248       fprintf (stderr, "Error %d detaching thread.\n", l_ret);
249       throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n");
250     }
251 #endif
252   };
253 };
254
255 typedef mld_thread_t mld_thread, *mld_thread_ptr;
256
257 #endif /* _INCLUDED_MLD_THREADS_H_ */