Wildmeshing Toolkit
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Private Attributes | List of all members
wmtk::SlotPool< T > Class Template Reference

Preallocated storage plus the atomic counter that hands slots out of it. More...

#include <SlotPool.hpp>

Public Types

using value_type = T
 

Public Member Functions

 SlotPool (const SlotPool &)=delete
 
SlotPooloperator= (const SlotPool &)=delete
 
size_t capacity () const
 Slots the storage can hold: the end of the spare region.
 
size_t live () const
 
void set_live (size_t n)
 Set the live count directly. For init and consolidate, which fill [0, n) themselves.
 
void resize (size_t n)
 Resize the storage. Does not touch the live count – the caller decides that.
 
void shrink_to_fit ()
 
void clear ()
 Drop the storage and the live count together, leaving an empty pool.
 
T & operator[] (size_t i)
 
const T & operator[] (size_t i) const
 
size_t request (size_t n)
 Atomically reserve n contiguous fresh slots.
 
Exhaustion flag

Set by request when it refuses, cleared by the owner at a pass boundary. A plain flag rather than a count: the response to exhaustion is to consolidate, which re-derives the capacity from the real element count, so the size of the shortfall is not an input.

bool refused () const
 
void clear_refused ()
 
Whole-storage iteration

These span [0, capacity()), spare region included – they are the vector's iterators, not the live range. Callers that want only live slots index [0, live()) instead.

auto begin ()
 
auto end ()
 
auto begin () const
 
auto end () const
 

Private Attributes

std::vector< T > m_data
 
std::atomic< size_t > m_live {0}
 
std::atomic< bool > m_refused {false}
 

Detailed Description

template<class T>
class wmtk::SlotPool< T >

Preallocated storage plus the atomic counter that hands slots out of it.

The mesh classes keep their connectivity in a vector that is deliberately larger than the live mesh: [0, live()) is filled, and [live(), capacity()) is spare headroom that operations consume. Operations run in parallel, so the counter is advanced with a CAS loop and a request that would run past capacity() is REFUSED rather than served by growing the storage – growing means reallocating, which would move the connectivity out from under concurrent readers. Callers ask for their slots up front and abort before mutating when the answer is a refusal.

Pairing the counter with the storage is the point of this class. The invariant that matters is live() <= capacity(), and it can only be checked – or maintained – where both are in reach. It is also the seat for any future growth strategy: implementing one here covers every allocation site in both meshes at once.

Not copyable or movable, because of the atomic. The meshes that hold these were already neither, for the same reason.

Note
Only request is safe to call concurrently. Everything else – resize, clear, set_live, shrink_to_fit – is for the serial points between passes, and operator[] is subject to the usual rule that a reader must not race the grower.

Member Function Documentation

◆ live()

template<class T >
size_t wmtk::SlotPool< T >::live ( ) const
inline

Slots handed out so far: the end of the live region, and the next index request would return. Named apart from capacity() because the two are genuinely different numbers, and conflating them is what makes the spare region hard to reason about.

◆ request()

template<class T >
size_t wmtk::SlotPool< T >::request ( size_t  n)
inline

Atomically reserve n contiguous fresh slots.

Returns
The first index of the block, or INVALID_SLOT if serving it would run past capacity(). A refusal leaves the counter untouched, so the slots that remain stay available to a later, smaller request; a request that leaked would push live() past capacity() and send subsequent iteration out of bounds.

n == 0 reports the current live() without consuming anything.


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