Fawkes API  Fawkes Development Version
mutex.cpp
1 
2 /***************************************************************************
3  * mutex.cpp - implementation of mutex, based on pthreads
4  *
5  * Generated: Thu Sep 14 17:03:57 2006
6  * Copyright 2006 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/exception.h>
25 #include <core/threading/mutex.h>
26 #include <core/threading/mutex_data.h>
27 #include <core/threading/thread.h>
28 
29 #include <pthread.h>
30 
31 namespace fawkes {
32 
33 /** @class Mutex core/threading/mutex.h
34  * Mutex mutual exclusion lock.
35  * This class is used in a multi-threading environment to lock access to
36  * resources. This is needed to prevent two threads from modifying a value
37  * at the same time or to prevent a thread from getting a dirty copy of
38  * a piece of data (the reader reads while a writer is writing, this could
39  * leave the data in a state where the reader reads half of the new and half
40  * of the old data).
41  *
42  * As a rule of thumb you should lock the mutex as short as possible and as
43  * long as needed. Locking the mutex too long will lead in a bad performance
44  * of the multi-threaded application because many threads are waiting for
45  * the lock and are not doing anything useful.
46  * If you do not lock enough code (and so serialize it) it will cause pain
47  * and errors.
48  *
49  * @ingroup Threading
50  * @ingroup FCL
51  * @see example_mutex_count.cpp
52  *
53  * @author Tim Niemueller
54  */
55 
56 /** Constructor.
57  * @param type mutex type
58  */
60 {
61  mutex_data = new MutexData();
62 
63  pthread_mutexattr_t attr;
64  pthread_mutexattr_init(&attr);
65  if (type == RECURSIVE) {
66  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
67  } else {
68  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
69  }
70 
71  pthread_mutex_init(&(mutex_data->mutex), &attr);
72 }
73 
74 /** Destructor */
76 {
77  pthread_mutex_destroy(&(mutex_data->mutex));
78  delete mutex_data;
79  mutex_data = NULL;
80 }
81 
82 /** Lock this mutex.
83  * A call to lock() will block until the lock on the mutex could be aquired.
84  * If you want to avoid see consider using try_lock().
85  */
86 void
88 {
89  int err = 0;
90  if ((err = pthread_mutex_lock(&(mutex_data->mutex))) != 0) {
91  throw Exception(err, "Failed to aquire lock for thread %s", Thread::current_thread()->name());
92  }
93 #ifdef DEBUG_THREADING
94  // do not switch order, lock holder must be protected with this mutex!
95  mutex_data->set_lock_holder();
96 #endif
97 }
98 
99 /** Tries to lock the mutex.
100  * This can also be used to check if a mutex is locked. The code for this
101  * can be:
102  *
103  * @code
104  * bool locked = false;
105  * if ( mutex->try_lock() ) {
106  * mutex->unlock();
107  * locked = true;
108  * }
109  * @endcode
110  *
111  * This cannot be implemented in Mutex in a locked() method since this
112  * would lead to race conditions in many situations.
113  *
114  * @return true, if the mutex could be locked, false otherwise.
115  */
116 bool
118 {
119  if (pthread_mutex_trylock(&(mutex_data->mutex)) == 0) {
120 #ifdef DEBUG_THREADING
121  mutex_data->set_lock_holder();
122 #endif
123  return true;
124  } else {
125  return false;
126  }
127 }
128 
129 /** Unlock the mutex. */
130 void
132 {
133 #ifdef DEBUG_THREADING
134  mutex_data->unset_lock_holder();
135  // do not switch order, lock holder must be protected with this mutex!
136 #endif
137  pthread_mutex_unlock(&(mutex_data->mutex));
138 }
139 
140 /** Shortly stop by at the mutex.
141  * This will just lock and unlock the mutex. It is equivalent to
142  * @code
143  * mutex->lock();
144  * mutex->unlock();
145  * @endcode
146  * This can be handy if you have to protect starvation and just have a stop-by
147  * mutex.
148  */
149 void
151 {
152  pthread_mutex_lock(&(mutex_data->mutex));
153  pthread_mutex_unlock(&(mutex_data->mutex));
154 }
155 
156 } // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
~Mutex()
Destructor.
Definition: mutex.cpp:75
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:117
Type
Mutex type.
Definition: mutex.h:38
@ RECURSIVE
A thread attempting to relock this mutex without first unlocking it shall succeed in locking the mute...
Definition: mutex.h:40
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void stopby()
Shortly stop by at the mutex.
Definition: mutex.cpp:150
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Mutex(Type type=NORMAL)
Constructor.
Definition: mutex.cpp:59
static Thread * current_thread()
Get the Thread instance of the currently running thread.
Definition: thread.cpp:1366
Fawkes library namespace.