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/threading/mutex.h>
25 #include <core/threading/mutex_data.h>
26 #include <core/threading/thread.h>
27 #include <core/exception.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 
57 /** Constructor.
58  * @param type mutex type
59  */
61 {
62  mutex_data = new MutexData();
63 
64  pthread_mutexattr_t attr;
65  pthread_mutexattr_init(&attr);
66  if (type == RECURSIVE) {
67  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
68  } else {
69  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
70  }
71 
72  pthread_mutex_init(&(mutex_data->mutex), &attr);
73 }
74 
75 /** Destructor */
77 {
78  pthread_mutex_destroy(&(mutex_data->mutex));
79  delete mutex_data;
80  mutex_data = NULL;
81 }
82 
83 
84 /** Lock this mutex.
85  * A call to lock() will block until the lock on the mutex could be aquired.
86  * If you want to avoid see consider using try_lock().
87  */
88 void
90 {
91  int err = 0;
92  if ( (err = pthread_mutex_lock(&(mutex_data->mutex))) != 0 ) {
93  throw Exception(err, "Failed to aquire lock for thread %s", Thread::current_thread()->name());
94  }
95 #ifdef DEBUG_THREADING
96  // do not switch order, lock holder must be protected with this mutex!
97  mutex_data->set_lock_holder();
98 #endif
99 }
100 
101 
102 /** Tries to lock the mutex.
103  * This can also be used to check if a mutex is locked. The code for this
104  * can be:
105  *
106  * @code
107  * bool locked = false;
108  * if ( mutex->try_lock() ) {
109  * mutex->unlock();
110  * locked = true;
111  * }
112  * @endcode
113  *
114  * This cannot be implemented in Mutex in a locked() method since this
115  * would lead to race conditions in many situations.
116  *
117  * @return true, if the mutex could be locked, false otherwise.
118  */
119 bool
121 {
122  if (pthread_mutex_trylock(&(mutex_data->mutex)) == 0) {
123 #ifdef DEBUG_THREADING
124  mutex_data->set_lock_holder();
125 #endif
126  return true;
127  } else {
128  return false;
129  }
130 }
131 
132 
133 /** Unlock the mutex. */
134 void
136 {
137 #ifdef DEBUG_THREADING
138  mutex_data->unset_lock_holder();
139  // do not switch order, lock holder must be protected with this mutex!
140 #endif
141  pthread_mutex_unlock(&(mutex_data->mutex));
142 }
143 
144 
145 /** Shortly stop by at the mutex.
146  * This will just lock and unlock the mutex. It is equivalent to
147  * @code
148  * mutex->lock();
149  * mutex->unlock();
150  * @endcode
151  * This can be handy if you have to protect starvation and just have a stop-by
152  * mutex.
153  */
154 void
156 {
157  pthread_mutex_lock(&(mutex_data->mutex));
158  pthread_mutex_unlock(&(mutex_data->mutex));
159 }
160 
161 
162 } // end namespace fawkes
Fawkes library namespace.
void unlock()
Unlock the mutex.
Definition: mutex.cpp:135
~Mutex()
Destructor.
Definition: mutex.cpp:76
Type
Mutex type.
Definition: mutex.h:38
Base class for exceptions in Fawkes.
Definition: exception.h:36
A thread attempting to relock this mutex without first unlocking it shall succeed in locking the mute...
Definition: mutex.h:40
static Thread * current_thread()
Get the Thread instance of the currently running thread.
Definition: thread.cpp:1318
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:120
void lock()
Lock this mutex.
Definition: mutex.cpp:89
Mutex(Type type=NORMAL)
Constructor.
Definition: mutex.cpp:60
void stopby()
Shortly stop by at the mutex.
Definition: mutex.cpp:155