rippled
Public Member Functions | Private Attributes | List of all members
ripple::packed_spinlock< T > Class Template Reference

Classes to handle arrays of spinlocks packed into a single atomic integer: More...

Public Member Functions

 packed_spinlock (packed_spinlock const &)=delete
 
packed_spinlockoperator= (packed_spinlock const &)=delete
 
 packed_spinlock (std::atomic< T > &lock, int index)
 A single spinlock packed inside the specified atomic. More...
 
bool try_lock ()
 
void lock ()
 
void unlock ()
 

Private Attributes

std::atomic< T > & bits_
 
const T mask_
 

Detailed Description

template<class T>
class ripple::packed_spinlock< T >

Classes to handle arrays of spinlocks packed into a single atomic integer:

Packed spinlocks allow for tremendously space-efficient lock-sharding but they come at a cost.

First, the implementation is necessarily low-level and uses advanced features like memory ordering and highly platform-specific tricks to maximize performance. This imposes a significant and ongoing cost to developers.

Second, and perhaps most important, is that the packing of multiple locks into a single integer which, albeit space-efficient, also has performance implications stemming from data dependencies, increased cache-coherency traffic between processors and heavier loads on the processor's load/store units.

To be sure, these locks can have advantages but they are definitely not general purpose locks and should not be thought of or used that way. The use cases for them are likely few and far between; without a compelling reason to use them, backed by profiling data, it might be best to use one of the standard locking primitives instead. Note that in most common platforms, std::mutex is so heavily optimized that it can, usually, outperform spinlocks.

Template Parameters
TAn unsigned integral type (e.g. std::uint16_t) A class that grabs a single packed spinlock from an atomic integer.

This class meets the requirements of Lockable: https://en.cppreference.com/w/cpp/named_req/Lockable

Definition at line 89 of file spinlock.h.

Constructor & Destructor Documentation

◆ packed_spinlock() [1/2]

template<class T >
ripple::packed_spinlock< T >::packed_spinlock ( packed_spinlock< T > const &  )
delete

◆ packed_spinlock() [2/2]

template<class T >
ripple::packed_spinlock< T >::packed_spinlock ( std::atomic< T > &  lock,
int  index 
)

A single spinlock packed inside the specified atomic.

Parameters
lockThe atomic integer inside which the spinlock is packed.
indexThe index of the spinlock this object acquires.
Note
For performance reasons, you should strive to have lock be on a cacheline by itself.

Definition at line 117 of file spinlock.h.

Member Function Documentation

◆ operator=()

template<class T >
packed_spinlock& ripple::packed_spinlock< T >::operator= ( packed_spinlock< T > const &  )
delete

◆ try_lock()

template<class T >
bool ripple::packed_spinlock< T >::try_lock ( )

Definition at line 124 of file spinlock.h.

◆ lock()

template<class T >
void ripple::packed_spinlock< T >::lock ( )

Definition at line 130 of file spinlock.h.

◆ unlock()

template<class T >
void ripple::packed_spinlock< T >::unlock ( )

Definition at line 144 of file spinlock.h.

Member Data Documentation

◆ bits_

template<class T >
std::atomic<T>& ripple::packed_spinlock< T >::bits_
private

Definition at line 92 of file spinlock.h.

◆ mask_

template<class T >
const T ripple::packed_spinlock< T >::mask_
private

Definition at line 102 of file spinlock.h.