Fawkes API Fawkes Development Version
spinlock.cpp
1
2/***************************************************************************
3 * spinlock.h - Spinlock
4 *
5 * Created: Wed Apr 02 13:20:31 2008
6 * Copyright 2006-2008 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/spinlock.h>
26#include <core/threading/thread.h>
27
28#include <pthread.h>
29#include <unistd.h>
30
31// cf. http://people.redhat.com/drepper/posix-option-groups.html
32#if defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS - 200112L) >= 0
33# define USE_POSIX_SPIN_LOCKS
34#else
35# undef USE_POSIX_SPIN_LOCKS
36# include <core/threading/mutex.h>
37#endif
38
39namespace fawkes {
40
41/** @class Spinlock <core/threading/spinlock.h>
42 * Spin lock.
43 * This class is similar to a Mutex in that it is used in a multi-threading
44 * environment to lock access to resources.
45 *
46 * The difference is that the spinlock will do a busy waiting until it acquires
47 * the lock while the mutex would block and wait, and may even starve if another
48 * threads releases a lock only for a short period of time.
49 *
50 * Spinlocks are risky, priority inversion may be caused if used improperly.
51 * Be sure what you are doing if you use spinlocks.
52 *
53 * @ingroup Threading
54 * @ingroup FCL
55 *
56 * @author Tim Niemueller
57 */
58
59/// @cond INTERNALS
60class SpinlockData
61{
62public:
63#ifdef USE_POSIX_SPIN_LOCKS
64 pthread_spinlock_t spinlock;
65#else
66 Mutex mutex;
67#endif
68};
69/// @endcond
70
71/** Constructor */
73{
74 spinlock_data = new SpinlockData();
75#ifdef USE_POSIX_SPIN_LOCKS
76 pthread_spin_init(&(spinlock_data->spinlock), PTHREAD_PROCESS_PRIVATE);
77#endif
78}
79
80/** Destructor */
82{
83#ifdef USE_POSIX_SPIN_LOCKS
84 pthread_spin_destroy(&(spinlock_data->spinlock));
85#endif
86 delete spinlock_data;
87 spinlock_data = NULL;
88}
89
90/** Lock this spinlock.
91 * A call to lock() will block until the lock on the spinlock could be aquired.
92 * If you want to avoid see consider using try_lock().
93 */
94void
96{
97#ifdef USE_POSIX_SPIN_LOCKS
98 int err = 0;
99 if ((err = pthread_spin_lock(&(spinlock_data->spinlock))) != 0) {
100 throw Exception(err, "Failed to aquire lock for thread %s", Thread::current_thread()->name());
101 }
102#else
103 bool locked = false;
104 while (!locked) {
105 locked = spinlock_data->mutex.try_lock();
106 }
107#endif
108}
109
110/** Tries to lock the spinlock.
111 * This can also be used to check if a spinlock is locked. The code for this
112 * can be:
113 *
114 * @code
115 * bool locked = false;
116 * if ( spinlock->try_lock() ) {
117 * spinlock->unlock();
118 * locked = true;
119 * }
120 * @endcode
121 *
122 * This cannot be implemented in Spinlock in a locked() method since this
123 * would lead to race conditions in many situations.
124 *
125 * @return true, if the spinlock could be locked, false otherwise.
126 */
127bool
129{
130#ifdef USE_POSIX_SPIN_LOCKS
131 if (pthread_spin_trylock(&(spinlock_data->spinlock)) == 0) {
132 return true;
133 } else {
134 return false;
135 }
136#else
137 return spinlock_data->mutex.try_lock();
138#endif
139}
140
141/** Unlock the spinlock. */
142void
144{
145#ifdef USE_POSIX_SPIN_LOCKS
146 pthread_spin_unlock(&(spinlock_data->spinlock));
147#else
148 spinlock_data->mutex.unlock();
149#endif
150}
151
152} // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
Spinlock()
Constructor.
Definition: spinlock.cpp:72
bool try_lock()
Tries to lock the spinlock.
Definition: spinlock.cpp:128
void lock()
Lock this spinlock.
Definition: spinlock.cpp:95
~Spinlock()
Destructor.
Definition: spinlock.cpp:81
void unlock()
Unlock the spinlock.
Definition: spinlock.cpp:143
static Thread * current_thread()
Get the Thread instance of the currently running thread.
Definition: thread.cpp:1366
Fawkes library namespace.