1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/********************************************************************************
* *
* S p i n l o c k C l a s s *
* *
*********************************************************************************
* Copyright (C) 2004,2022 by Jeroen van der Zijp. All Rights Reserved. *
*********************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
********************************************************************************/
#ifndef FXSPINLOCK_H
#define FXSPINLOCK_H
namespace FX {
/**
* FXSpinLock can be used to provide safe access to very small critical sections.
*
* Similar to FXMutex, a FXSpinLock provides safe access to a critical section
* shared by multiple threads. Unlike FXMutex, however, a thread which is unable
* to obtain the lock will not block, but spin in a tight loop until the lock can
* be obtained. The advantage of FXSpinLock over FXMutex is that no operating
* system calls are performed suspending and resuming the calling thread.
*/
class FXAPI FXSpinLock {
private:
volatile FXuval data[4];
private:
FXSpinLock(const FXSpinLock&);
FXSpinLock &operator=(const FXSpinLock&);
public:
/// Initialize the spinlock
FXSpinLock();
/// Lock the spinlock
void lock();
/// Return true if succeeded locking the spinlock
FXbool trylock();
/// Return true if spinlock is already locked
FXbool locked();
/// Unlock spinlock
void unlock();
/// Delete the spinlock
~FXSpinLock();
};
/**
* Establish a correspondence between a C++ scope and an FXSpinLock,
* so that entering and leaving the scope in which the scoped lock
* is defined will automatically lock and unlock the associated
* spin lock.
* This will typically result in much less coding, and in addition
* will make the code safe from exceptions.
*/
class FXAPI FXScopedSpinLock {
private:
FXSpinLock& spn;
private:
FXScopedSpinLock();
FXScopedSpinLock(const FXScopedSpinLock&);
FXScopedSpinLock& operator=(const FXScopedSpinLock&);
public:
/// Construct & lock associated spinlock
FXScopedSpinLock(FXSpinLock& s):spn(s){ lock(); }
/// Return reference to associated spinlock
FXSpinLock& spinlock(){ return spn; }
/// Lock spinlock
void lock(){ spn.lock(); }
/// Return true if succeeded locking the spinlock
FXbool trylock(){ return spn.trylock(); }
/// Return true if spinlock is already locked
FXbool locked(){ return spn.locked(); }
/// Unlock spin lock
void unlock(){ spn.unlock(); }
/// Destroy and unlock associated spinlock
~FXScopedSpinLock(){ unlock(); }
};
/**
* The reverse spin lock unlocks its associated FXSpinLock when entering
* the scope, and automatically relocks it upon exiting the scope.
* Exceptions raised while in this region will automatically relock
* the spin lock upon leaving the enclosing scope.
*/
class FXAPI FXReverseSpinLock {
private:
FXSpinLock& spn;
private:
FXReverseSpinLock();
FXReverseSpinLock(const FXReverseSpinLock&);
FXReverseSpinLock& operator=(const FXReverseSpinLock&);
public:
/// Construct and unlock associated spin lock
FXReverseSpinLock(FXSpinLock& s):spn(s){ unlock(); }
/// Return reference to associated spin lock
FXSpinLock& spinlock(){ return spn; }
/// Lock spin lock
void lock(){ spn.lock(); }
/// Return true if succeeded locking the spin lock
FXbool trylock(){ return spn.trylock(); }
/// Return true if spin lock is already locked
FXbool locked(){ return spn.locked(); }
/// Unlock spin lock
void unlock(){ spn.unlock(); }
/// Destroy and relock associated spin lock
~FXReverseSpinLock(){ lock(); }
};
}
#endif
|