Fawkes API  Fawkes Development Version
mutex_locker.cpp
1 
2 /***************************************************************************
3  * mutex_locker.cpp - mutex locker helper
4  *
5  * Created: Thu Oct 04 16:14:30 2007
6  * Copyright 2006-2007 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_locker.h>
26 
27 namespace fawkes {
28 
29 /** @class MutexLocker <core/threading/mutex_locker.h>
30  * Mutex locking helper.
31  * This class is a convenience function which can help you prevent a quite
32  * a few headaches. Consider the following code.
33  * @code
34  * void my_function()
35  * {
36  * mutex->lock();
37  * for (int i = 0; i < LIMIT; ++i) {
38  * if ( failure ) {
39  * mutex->unlock
40  * }
41  * }
42  *
43  * switch ( someval ) {
44  * VALA:
45  * mutex->unlock();
46  * return;
47  * VALB:
48  * do_something();
49  * }
50  *
51  * try {
52  * do_function_that_throws_exceptions();
53  * } catch (Exception &e) {
54  * mutex->unlock();
55  * throw;
56  * }
57  * mutex->unlock();
58  * }
59  * @endcode
60  * This is not a complete list of examples but as you see if you have many
61  * exit points in a function it becomes more and more work to have correct
62  * locking behavior.
63  *
64  * This is a lot simpler with the MutexLocker. The MutexLocker locks the
65  * given mutex on creation, and unlocks it in the destructor. If you now
66  * have a mutex locker on the stack as integral type the destructor is
67  * called automagically on function exit and thus the mutex is appropriately
68  * unlocked.
69  * The code would look like this:
70  * @code
71  * void my_function()
72  * {
73  * MutexLocker ml(mutex);
74  * // do anything, no need to call mutex->lock()/unlock() if only has to be
75  * // called on entering and exiting the function.
76  * }
77  * @endcode
78  *
79  * @ingroup Threading
80  * @ingroup FCL
81  *
82  * @author Tim Niemueller
83  */
84 
85 /** Constructor.
86  * @param mutex Mutex to lock/unlock appropriately.
87  * @param initially_lock true to lock the mutex in the constructor, false to not lock
88  */
89 MutexLocker::MutexLocker(RefPtr<Mutex> mutex, bool initially_lock)
90 {
91  rawmutex_ = 0;
92  refmutex_ = mutex;
93  if (initially_lock) {
94  refmutex_->lock();
95  }
96  locked_ = initially_lock;
97 }
98 
99 /** Constructor.
100  * @param mutex Mutex to lock/unlock appropriately.
101  * @param initially_lock true to lock the mutex in the constructor, false to not lock
102  */
103 MutexLocker::MutexLocker(Mutex *mutex, bool initially_lock)
104 {
105  rawmutex_ = mutex;
106  if (initially_lock) {
107  rawmutex_->lock();
108  }
109  locked_ = initially_lock;
110 }
111 
112 /** Constructor.
113  * @param mutex Mutex to lock/unlock appropriately.
114  * @param initially_lock true to lock the mutex in the constructor, false to not lock
115  */
116 MutexLocker::MutexLocker(Mutex &mutex, bool initially_lock)
117 {
118  rawmutex_ = &mutex;
119  if (initially_lock) {
120  rawmutex_->lock();
121  }
122  locked_ = initially_lock;
123 }
124 
125 /** Destructor */
127 {
128  if (locked_) {
129  if (rawmutex_) {
130  rawmutex_->unlock();
131  } else {
132  refmutex_->unlock();
133  }
134  }
135 }
136 
137 /** Lock this mutex, again.
138  * Use this if you unlocked the mutex from the outside.
139  */
140 void
142 {
143  if (rawmutex_) {
144  rawmutex_->lock();
145  } else {
146  refmutex_->lock();
147  }
148  locked_ = true;
149 }
150 
151 /** Unlock the mutex. */
152 void
154 {
155  locked_ = false;
156  if (rawmutex_) {
157  rawmutex_->unlock();
158  } else {
159  refmutex_->unlock();
160  }
161 }
162 
163 } // end namespace fawkes
fawkes::Mutex::lock
void lock()
Lock this mutex.
Definition: mutex.cpp:87
fawkes::Mutex
Mutex mutual exclusion lock.
Definition: mutex.h:33
fawkes::RefPtr
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:50
fawkes::Mutex::unlock
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
fawkes::MutexLocker::MutexLocker
MutexLocker(RefPtr< Mutex > mutex, bool initially_lock=true)
Constructor.
Definition: mutex_locker.cpp:89
fawkes
Fawkes library namespace.
fawkes::MutexLocker::relock
void relock()
Lock this mutex, again.
Definition: mutex_locker.cpp:141
fawkes::MutexLocker::~MutexLocker
~MutexLocker()
Destructor.
Definition: mutex_locker.cpp:126
fawkes::MutexLocker::unlock
void unlock()
Unlock the mutex.
Definition: mutex_locker.cpp:153