Quick Links:

bal | bbl | bdl | bsl

Public Types | Public Member Functions | Static Public Member Functions

bdlcc::FixedQueueIndexManager Class Reference

#include <bdlcc_fixedqueueindexmanager.h>

List of all members.

Public Types

enum  { k_MAX_CAPACITY = 1 << ((sizeof(int) * 8) - 2), e_MAX_CAPACITY = k_MAX_CAPACITY }

Public Member Functions

 BSLMF_NESTED_TRAIT_DECLARATION (FixedQueueIndexManager, bslma::UsesBslmaAllocator)
 FixedQueueIndexManager (bsl::size_t capacity, bslma::Allocator *basicAllocator=0)
 ~FixedQueueIndexManager ()
int reservePushIndex (unsigned int *generation, unsigned int *index)
void commitPushIndex (unsigned int generation, unsigned int index)
int reservePopIndex (unsigned int *generation, unsigned int *index)
void commitPopIndex (unsigned int generation, unsigned int index)
void disable ()
void enable ()
int reservePopIndexForClear (unsigned int *disposedGeneration, unsigned int *disposedIndex, unsigned int endGeneration, unsigned int endIndex)
void abortPushIndexReservation (unsigned int generation, unsigned int index)
bool isEnabled () const
bsl::size_t length () const
bsl::size_t capacity () const
bsl::ostream & print (bsl::ostream &stream) const

Static Public Member Functions

static int circularDifference (unsigned int minuend, unsigned int subtrahend, unsigned int modulo)
static unsigned int numRepresentableGenerations (bsl::size_t capacity)

Detailed Description

This class implements a circular buffer of atomic state variables. These are intended to synchronize access to another (non-atomic) indexed data structure so that the other data structure can be used as a thread-enabled fixed-size queue.

See Component bdlcc_fixedqueueindexmanager


Member Enumeration Documentation

anonymous enum
Enumerator:
k_MAX_CAPACITY 

maximum capacity of an index manager; note that 2 bits of d_pushIndex are reserved for holding the disabled status flag, and ensuring that the representable number of generation counts is at least 2 (see the implementation note in the .cpp for more details)

e_MAX_CAPACITY 

Constructor & Destructor Documentation

bdlcc::FixedQueueIndexManager::FixedQueueIndexManager ( bsl::size_t  capacity,
bslma::Allocator basicAllocator = 0 
) [explicit]

Create an index manager for a circular buffer having the specified maximum capacity. Optionally specify a basicAllocator used to supply memory. If basicAllocator is 0, the currently installed default allocator is used. isEnabled will be true for the newly created index manager. The behavior is undefined unless 0 < capacity and capacity <= k_MAX_CAPACITY.

bdlcc::FixedQueueIndexManager::~FixedQueueIndexManager (  ) 

Destroy this object.


Member Function Documentation

bdlcc::FixedQueueIndexManager::BSLMF_NESTED_TRAIT_DECLARATION ( FixedQueueIndexManager  ,
bslma::UsesBslmaAllocator   
)
static int bdlcc::FixedQueueIndexManager::circularDifference ( unsigned int  minuend,
unsigned int  subtrahend,
unsigned int  modulo 
) [static]

Return the difference between the specified minuend and the specified subtrahend (typically minuend - subtrahend) where minuend and subtrahend are both "circular values", meaning they are part of a non-euclidean number line where the value wrap around to 0 at the specified modulo. The difference between two circular values is the minimum of either the number of increments or the number of decrements to subtrahend that results in minuend (i.e., the minimum "distance" between the points on the number circle), where increments are a positive difference, and decrements are a negative difference. If the number of increments and number of decrements between minuend and subtrahend are equal, minuend - subtrahend is returned. For example, for a hypothetical compass, [0, 360):

          circularDifference(   0, 359, 360) ==    1
          circularDifference( 359,   0, 360) ==   -1
          circularDifference( 180,   0, 360) ==  180
          circularDifference(   0, 180, 360) == -180

The behavior is undefined unless minuend < modulo, subtrahend < modulo, and modulo <= INT_MAX + 1.

static unsigned int bdlcc::FixedQueueIndexManager::numRepresentableGenerations ( bsl::size_t  capacity  )  [static]

Return the number of representable generations for a circular buffer of the specified capacity.

int bdlcc::FixedQueueIndexManager::reservePushIndex ( unsigned int *  generation,
unsigned int *  index 
)

Reserve the next available index at which to enqueue an element in an (externally managed) circular buffer; load the specified index with the reserved index and load the specified generation with the current generation of the circular buffer. Return 0 on success, a negative value if the queue is disabled, and a positive value if the queue is full. If this method succeeds, other threads using this object may spin on the corresponding index state until commitPushIndex is called using the returned index and generation values; clients should call commitPushIndex quickly after this method returns, without performing any blocking operations. If this method fails the generation and index will be unmodified. The behavior is undefined if the current thread is already holding a reservation on either a push or pop index. Note that generation is necessary for invoking commitPushIndex but should not otherwise be used by the caller; the value reflects the number of times the index in the circular buffer has been used.

void bdlcc::FixedQueueIndexManager::commitPushIndex ( unsigned int  generation,
unsigned int  index 
)

Mark the specified index as occupied (full) in the specified generation. The behavior is undefined unless generation and index match those returned by a previous successful call to reservePushIndex (that has not previously been committed).

int bdlcc::FixedQueueIndexManager::reservePopIndex ( unsigned int *  generation,
unsigned int *  index 
)

Reserve the next available index from which to dequeue an element from an (externally managed) circular buffer; load the specified index with the reserved index and load the specified generation with the current generation of the circular buffer. Return 0 on success, and a non-zero value if the queue is empty. If this method succeeds, other threads using this object may spin on the corresponding index state until commitPopIndex is called using the returned index and generation values; clients should call commitPopIndex quickly after this method returns, without performing any blocking operations. If this method fails the generation and index will be unmodified. The behavior is undefined if the current thread is already holding a reservation on either a push or pop index. Note that generation is necessary for invoking commitPopIndex but should not otherwise be used by the caller; the value reflects the of times the index in the circular buffer has been used.

void bdlcc::FixedQueueIndexManager::commitPopIndex ( unsigned int  generation,
unsigned int  index 
)

Mark the specified index as available (empty) in the generation following the specified generation. The behavior is undefined unless generation and index' match those returned by a previous successful call to reservePopIndex (that has not previously been committed).

void bdlcc::FixedQueueIndexManager::disable (  ) 

Mark the queue as disabled. Future calls to reservePushIndex will fail.

void bdlcc::FixedQueueIndexManager::enable (  ) 

Mark the queue as enabled.

int bdlcc::FixedQueueIndexManager::reservePopIndexForClear ( unsigned int *  disposedGeneration,
unsigned int *  disposedIndex,
unsigned int  endGeneration,
unsigned int  endIndex 
)

If the next available index from which an element can be popped is before the specified endGeneration and endIndex then reserve that index for popping and load the specified disposedGeneration and disposedIndex with the generation and index of the reserved cell; otherwise this operation has no effect. Return 0 if an index was successfully reserved, and a non-zero value if the current pop index is at endIndex and endGeneration. The behavior is undefined unless endGeneration and endIndex refer to a cell that has been acquired for writing. Note that this operation is used to facilitate removing all the elements in a circular buffer if an exception is thrown between reserving an index for pushing, and committing that index -- the intended usage is to call reservePopIndexForClear and then commitPopIndex, emptying all the cells up to the index that was reserved for writing, and then call abortPushIndexReservation on the reserved index.

void bdlcc::FixedQueueIndexManager::abortPushIndexReservation ( unsigned int  generation,
unsigned int  index 
)

Release the specified index and make it available for use in the generation following the specified generation. The behavior is undefined unless the calling thread holds a reservation on generation and index, and clearPopIndex and then commitPushIndex have been repeatedly invoked with generation and index as input until no indices remain to clear. Note that this operation is used to facilitate removing all the elements in a circular buffer if an exception is thrown between reserving an index for pushing, and committing that index.

bool bdlcc::FixedQueueIndexManager::isEnabled (  )  const

Return true if the queue is enabled, and false if it is disabled.

bsl::size_t bdlcc::FixedQueueIndexManager::length (  )  const

Return a snapshot of the number of items in the queue.

bsl::size_t bdlcc::FixedQueueIndexManager::capacity (  )  const

Return the maximum number of items that may be stored in the queue.

bsl::ostream& bdlcc::FixedQueueIndexManager::print ( bsl::ostream &  stream  )  const

Print a formatted string describing the current state of this object to the specified stream. If stream is not valid on entry, this operation has no effect. Note that this method describes the internal state of the buffer and is provided purely for debugging purposes.


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