DUDS
Distributed Update of Data from Something
duds::general::Spinlock Class Reference

A simple spinlock following the lockable and timed lockable concepts so that it can be used with std::lock_guard, std::unique_lock, and std::lock. More...

#include <Spinlock.hpp>

Inheritance diagram for duds::general::Spinlock:
Collaboration diagram for duds::general::Spinlock:

Public Member Functions

 Spinlock ()
 Makes a Spinlock in the unlocked state. More...
 
 ~Spinlock ()
 Locks the spinlock before destruction to delay destruction in case of a lock. More...
 
void lock ()
 A spiny busy or yielding wait that ends with ownership of the lock. More...
 
void lockAlwaysYield ()
 A yielding wait that ends with ownership of the lock. More...
 
void lockNeverYield ()
 A spiny busy wait that ends with ownership of the lock. More...
 
bool try_lock ()
 A single attempt at gaining ownership of the lock. More...
 
template<class Rep , class Period >
bool try_lock_for (const std::chrono::duration< Rep, Period > &duration)
 A spiny busy wait or yielding wait that ends with ownership of the lock if ownership can be granted within duration. More...
 
template<class Clock , class Duration >
bool try_lock_until (const std::chrono::time_point< Clock, Duration > &time)
 A spiny busy wait or a yielding wait that ends with ownership of the lock if ownership can be granted before time. More...
 
template<class Rep , class Period >
bool tryLockAlwaysYeildFor (const std::chrono::duration< Rep, Period > &duration)
 A yielding wait that ends with ownership of the lock if ownership can be granted within duration. More...
 
template<class Clock , class Duration >
bool tryLockAlwaysYeildUntil (const std::chrono::time_point< Clock, Duration > &time)
 A yielding wait that ends with ownership of the lock if ownership can be granted before time. More...
 
template<class Rep , class Period >
bool tryLockNeverYeildFor (const std::chrono::duration< Rep, Period > &duration)
 A spiny busy wait that ends with ownership of the lock if ownership can be granted within duration. More...
 
template<class Clock , class Duration >
bool tryLockNeverYeildUntil (const std::chrono::time_point< Clock, Duration > &time)
 A spiny busy wait that ends with ownership of the lock if ownership can be granted before time. More...
 
void unlock ()
 Releases ownership of the lock. More...
 

Private Attributes

std::atomic_flag af
 Used like a mutually exclusive semaphore, but doesn't involve the operating system. More...
 

Static Private Attributes

static bool useYield = std::thread::hardware_concurrency() == 1
 True when lock() should call yield in its loop; good for uniprocessor, unicore systems. More...
 

Detailed Description

A simple spinlock following the lockable and timed lockable concepts so that it can be used with std::lock_guard, std::unique_lock, and std::lock.

Spinlock is a simple veneer over std::atomic_flag to keep the code using it a little simpler. As long as the locks are held very briefly, or longer locks are very uncommon, this should have less overhead than std::mutex.

The spin lock can optionally call std::this_thread::yield() between attempts to acquire the lock. The functions implementing the C++ concepts for compatablity with the C++ lock objects will yield if the host system reports that it can only run a single thread at a time (std::thread::hardware_concurrency() == 1), and otherwise will not yeild. Functions that always yield and never yield are also providied. In cases where a yield will work better on all hosts, SpinlockYieldingWrapper can be used with C++ lock objects to always yield.

A class that uses a spin lock that may have a member function using the lock when its destructor is called on another thread should declare the spin lock as its last non-static member to delay destruction until after a lock can be acquired.

Note
Should a spinlock show up in the C++ libraries, this class will be deprecated.
Warning
To promote preformance, there are no run-time checks to ensure proper usage. One thread could unlock what another thread locked. To help avoid misuse, std::lock_guard, std::unique_lock, or something similar should be used instead of directly calling functions on this class.
Author
Jeff Jackowski

Definition at line 52 of file Spinlock.hpp.

Constructor & Destructor Documentation

◆ Spinlock()

duds::general::Spinlock::Spinlock ( )
inline

Makes a Spinlock in the unlocked state.

Definition at line 67 of file Spinlock.hpp.

◆ ~Spinlock()

duds::general::Spinlock::~Spinlock ( )
inline

Locks the spinlock before destruction to delay destruction in case of a lock.

Definition at line 76 of file Spinlock.hpp.

Member Function Documentation

◆ lock()

void duds::general::Spinlock::lock ( )
inline

A spiny busy or yielding wait that ends with ownership of the lock.

Yield will be used if useYield is true, which is the default for single processor systems.

Definition at line 109 of file Spinlock.hpp.

Referenced by ~Spinlock().

◆ lockAlwaysYield()

void duds::general::Spinlock::lockAlwaysYield ( )
inline

A yielding wait that ends with ownership of the lock.

Every time the lock in not acquired, yield is called to allow other threads a chance to run, and maybe unlock the resource. This works well on single processor systems since if the lock is taken another thread must run to unlock it. On multi-processor systems, this could make the lock take longer.

Definition at line 98 of file Spinlock.hpp.

Referenced by lock(), and duds::general::SpinlockYieldingWrapper::lock().

◆ lockNeverYield()

void duds::general::Spinlock::lockNeverYield ( )
inline

A spiny busy wait that ends with ownership of the lock.

This is best used on multi-processor systems; mult-core counts. On single processor systems, this will eat processor time until the operating system preempts the thread.

Definition at line 86 of file Spinlock.hpp.

Referenced by lock().

◆ try_lock()

bool duds::general::Spinlock::try_lock ( )
inline

A single attempt at gaining ownership of the lock.

This may not be very useful with a spinlock, but it was easy, so I implemented it.

Returns
True if ownership of the lock was granted.

Definition at line 121 of file Spinlock.hpp.

Referenced by duds::general::SpinlockYieldingWrapper::try_lock().

◆ try_lock_for()

template<class Rep , class Period >
bool duds::general::Spinlock::try_lock_for ( const std::chrono::duration< Rep, Period > &  duration)
inline

A spiny busy wait or yielding wait that ends with ownership of the lock if ownership can be granted within duration.

Parameters
durationThe maximum time span to wait for the lock.
Returns
True if ownership of the lock was granted.

Definition at line 198 of file Spinlock.hpp.

◆ try_lock_until()

template<class Clock , class Duration >
bool duds::general::Spinlock::try_lock_until ( const std::chrono::time_point< Clock, Duration > &  time)
inline

A spiny busy wait or a yielding wait that ends with ownership of the lock if ownership can be granted before time.

Parameters
timeWhen to give up attempting to lock.
Returns
True if ownership of the lock was granted.

Definition at line 164 of file Spinlock.hpp.

◆ tryLockAlwaysYeildFor()

template<class Rep , class Period >
bool duds::general::Spinlock::tryLockAlwaysYeildFor ( const std::chrono::duration< Rep, Period > &  duration)
inline

A yielding wait that ends with ownership of the lock if ownership can be granted within duration.

Parameters
durationThe maximum time span to wait for the lock.
Returns
True if ownership of the lock was granted.

Definition at line 188 of file Spinlock.hpp.

Referenced by try_lock_for(), and duds::general::SpinlockYieldingWrapper::try_lock_for().

◆ tryLockAlwaysYeildUntil()

template<class Clock , class Duration >
bool duds::general::Spinlock::tryLockAlwaysYeildUntil ( const std::chrono::time_point< Clock, Duration > &  time)
inline

A yielding wait that ends with ownership of the lock if ownership can be granted before time.

Parameters
timeWhen to give up attempting to lock.
Returns
True if ownership of the lock was granted.

Definition at line 147 of file Spinlock.hpp.

Referenced by try_lock_until(), duds::general::SpinlockYieldingWrapper::try_lock_until(), and tryLockAlwaysYeildFor().

◆ tryLockNeverYeildFor()

template<class Rep , class Period >
bool duds::general::Spinlock::tryLockNeverYeildFor ( const std::chrono::duration< Rep, Period > &  duration)
inline

A spiny busy wait that ends with ownership of the lock if ownership can be granted within duration.

Parameters
durationThe maximum time span to wait for the lock.
Returns
True if ownership of the lock was granted.

Definition at line 178 of file Spinlock.hpp.

Referenced by try_lock_for().

◆ tryLockNeverYeildUntil()

template<class Clock , class Duration >
bool duds::general::Spinlock::tryLockNeverYeildUntil ( const std::chrono::time_point< Clock, Duration > &  time)
inline

A spiny busy wait that ends with ownership of the lock if ownership can be granted before time.

Parameters
timeWhen to give up attempting to lock.
Returns
True if ownership of the lock was granted.

Definition at line 132 of file Spinlock.hpp.

Referenced by try_lock_until(), and tryLockNeverYeildFor().

◆ unlock()

void duds::general::Spinlock::unlock ( )
inline

Releases ownership of the lock.

Definition at line 208 of file Spinlock.hpp.

Referenced by Spinlock(), and duds::general::SpinlockYieldingWrapper::unlock().

Member Data Documentation

◆ af

std::atomic_flag duds::general::Spinlock::af
private

Used like a mutually exclusive semaphore, but doesn't involve the operating system.

Definition at line 57 of file Spinlock.hpp.

◆ useYield

bool duds::general::Spinlock::useYield = std::thread::hardware_concurrency() == 1
staticprivate

True when lock() should call yield in its loop; good for uniprocessor, unicore systems.

Definition at line 62 of file Spinlock.hpp.


The documentation for this class was generated from the following files: