NEURON
neuron::container::soa< Storage, Tags > Struct Template Reference

Utility for generating SOA data structures. More...

#include <neuron/container/soa_container.hpp>

Public Types

using frozen_token_type = state_token< Storage >
 Return type of issue_frozen_token() More...
 

Public Member Functions

 soa ()
 Construct with default-constructed tag type instances. More...
 
 soa (Tags... tag_instances)
 Construct with specific tag instances. More...
 
 soa (soa &&)=delete
 soa is not movable More...
 
 soa (soa const &)=delete
 soa is not copiable More...
 
soaoperator= (soa &&)=delete
 soa is not move assignable More...
 
soaoperator= (soa const &)=delete
 soa is not copy assignable More...
 
std::size_t size () const
 Get the size of the container. More...
 
bool empty () const
 Test if the container is empty. More...
 
void shrink_to_fit ()
 
frozen_token_type issue_frozen_token ()
 Create a token guaranteeing the container is in "frozen" state. More...
 
void mark_as_sorted (frozen_token_type &write_token)
 Tell the container it is sorted. More...
 
void mark_as_unsorted ()
 Tell the container it is no longer sorted. More...
 
void set_unsorted_callback (std::function< void()> unsorted_callback)
 Set the callback that is invoked when the container becomes unsorted. More...
 
bool is_sorted () const
 Query if the underlying vectors are still "sorted". More...
 
template<typename Arg >
frozen_token_type apply_reverse_permutation (Arg &&permutation)
 Permute the SoA-format data using an arbitrary range of integers. More...
 
template<typename Range >
void apply_reverse_permutation (Range permutation, frozen_token_type &sorted_token)
 Permute the SoA-format data using an arbitrary range of integers. More...
 
non_owning_identifier< Storage > at (std::size_t offset) const
 Get a non-owning identifier to the offset-th entry. More...
 
template<typename Tag >
constexpr Tag const & get_tag () const
 Get the instance of the given tag type. More...
 
template<typename Tag >
Tag::typeget (std::size_t offset)
 Get the offset-th element of the column named by Tag. More...
 
template<typename Tag >
Tag::type const & get (std::size_t offset) const
 Get the offset-th element of the column named by Tag. More...
 
template<typename Tag >
data_handle< typename Tag::typeget_handle (non_owning_identifier_without_container id, int array_index=0) const
 Get a handle to the given element of the column named by Tag. More...
 
template<typename Tag >
data_handle< typename Tag::typeget_field_instance_handle (non_owning_identifier_without_container id, int field_index, int array_index=0) const
 Get a handle to the given element of the field_index-th column named by Tag. More...
 
template<typename Tag >
Tag::typeget_field_instance (std::size_t offset, int field_index, int array_index=0)
 Get the offset-th element of the field_index-th instance of the column named by Tag. More...
 
template<typename Tag >
Tag::type const & get_field_instance (std::size_t offset, int field_index, int array_index=0) const
 Get the offset-th element of the field_index-th instance of the column named by Tag. More...
 
non_owning_identifier_without_container get_identifier (std::size_t offset) const
 Get the offset-th identifier. More...
 
neuron::container::generic_data_handle find_data_handle (neuron::container::generic_data_handle input_handle) const
 Return a permutation-stable handle if ptr is inside us. More...
 
template<typename Tag >
bool is_storage_pointer (typename Tag::type const *ptr) const
 Query whether the given pointer-to-vector is the one associated to Tag. More...
 
std::unique_ptr< utils::storage_infofind_container_info (void const *cont) const
 Check if cont refers to a field in this container. More...
 
template<typename Tag >
Tag::type *const * get_data_ptrs () const
 Get a pointer to a range of pointers that always point to the start of the contiguous storage. More...
 
template<typename Tag >
int const * get_array_dims () const
 Get a pointer to an array holding the array dimensions of the fields associated with this tag. More...
 
template<typename Tag >
int get_array_dims (int field_index) const
 
template<typename Tag >
size_t get_num_variables () const
 
template<typename Tag >
int const * get_array_dim_prefix_sums () const
 Get a pointer to an array holding the prefix sum of array dimensions for this tag. More...
 
template<typename Tag >
field_index translate_legacy_index (int legacy_index) const
 
template<typename Tag >
bool field_active () const
 Query whether the field associated with the given tag is active. More...
 
template<typename... TagsToChange>
void set_field_status (bool enabled)
 Enable/disable the fields associated with the given tags. More...
 
StorageMemoryUsage memory_usage () const
 

Static Public Attributes

template<typename Tag >
static constexpr bool has_tag_v = detail::type_in_pack_v<Tag, Tags...>
 

Private Member Functions

void erase (std::size_t i)
 Remove the \(i^{\text{th}}\) row from the container. More...
 
template<detail::may_cause_reallocation might_reallocate, typename Callable >
Callable for_each_vector (Callable callable)
 Apply the given function to non-const versions of all vectors. More...
 
template<detail::may_cause_reallocation might_reallocate, typename Callable , typename Tag , typename... RemainingTags>
Callable for_each_tag_vector_impl (Callable callable)
 
template<detail::may_cause_reallocation , typename Callable >
Callable for_each_tag_vector_impl (Callable callable)
 
template<typename Callable >
Callable for_each_vector (Callable callable) const
 Apply the given function to const-qualified versions of all vectors. More...
 
template<typename Callable , typename Tag , typename... RemainingTags>
Callable for_each_tag_vector_impl (Callable callable) const
 
template<typename Callable >
Callable for_each_tag_vector_impl (Callable callable) const
 
void increase_frozen_count ()
 Record that a state_token was copied. More...
 
void decrease_frozen_count ()
 Flag that the storage is no longer frozen. More...
 
template<bool internal>
void mark_as_unsorted_impl ()
 Set m_sorted = false and execute the callback. More...
 
owning_identifier< Storage > acquire_owning_identifier ()
 Create a new entry and return an identifier that owns it. More...
 
void throw_error (std::string_view message) const
 Throw an exception with a pretty prefix. More...
 

Private Attributes

std::mutex m_mut {}
 Mutex to protect m_frozen_count and m_sorted. More...
 
bool m_sorted {false}
 Flag for issue_frozen_token(), mark_as_unsorted() and is_sorted(). More...
 
std::size_t m_frozen_count {}
 Reference count for tokens guaranteeing the container is frozen. More...
 
std::vector< non_owning_identifier_without_containerm_indices {}
 Pointers to identifiers that record the current physical row. More...
 
std::tuple< detail::field_data< Tags, detail::field_impl_v< Tags > >... > m_data {}
 Collection of data columns. More...
 
std::function< void()> m_unsorted_callback {}
 Callback that is invoked when the container becomes unsorted. More...
 

Static Private Attributes

template<typename Tag >
static constexpr std::size_t tag_index_v = detail::index_of_type_v<Tag, Tags...>
 

Friends

struct state_token< Storage >
 
struct owning_identifier< Storage >
 

Detailed Description

template<typename Storage, typename... Tags>
struct neuron::container::soa< Storage, Tags >

Utility for generating SOA data structures.

Template Parameters
StorageName of the actual storage type derived from soa<...>.
TagsParameter pack of tag types that define the columns included in the container. Types may not be repeated.

This CRTP base class is used to implement the ~global SOA storage structs that hold (so far) Node and Mechanism data. Ownership of rows in these structs is managed via instances of the owning identifier type neuron::container::owning_identifier instantiated with Storage, and non-owning reference to rows in the data structures are managed via instances of the neuron::container::non_owning_identifier template instantiated with Storage. These identifiers are typically wrapped in a data-structure-specific (i.e. Node- or Mechanism-specific) interface type that provides data-structure-specific accessors and methods to obtain actual data values and more generic handle types such as neuron::container::data_handle<T> and neuron::container::generic_data_handle.

Definition at line 683 of file soa_container.hpp.

Member Typedef Documentation

◆ frozen_token_type

template<typename Storage , typename... Tags>
using neuron::container::soa< Storage, Tags >::frozen_token_type = state_token<Storage>

Return type of issue_frozen_token()

Definition at line 923 of file soa_container.hpp.

Constructor & Destructor Documentation

◆ soa() [1/4]

template<typename Storage , typename... Tags>
neuron::container::soa< Storage, Tags >::soa ( )
inline

Construct with default-constructed tag type instances.

Definition at line 687 of file soa_container.hpp.

◆ soa() [2/4]

template<typename Storage , typename... Tags>
neuron::container::soa< Storage, Tags >::soa ( Tags...  tag_instances)
inline

Construct with specific tag instances.

This is useful if the tag types are not empty, for example if the number of times a column is duplicated is a runtime value.

Definition at line 696 of file soa_container.hpp.

◆ soa() [3/4]

template<typename Storage , typename... Tags>
neuron::container::soa< Storage, Tags >::soa ( soa< Storage, Tags > &&  )
delete

soa is not movable

This is to make it harder to accidentally invalidate pointers-to-storage in handles.

◆ soa() [4/4]

template<typename Storage , typename... Tags>
neuron::container::soa< Storage, Tags >::soa ( soa< Storage, Tags > const &  )
delete

soa is not copiable

This is partly to make it harder to accidentally invalidate pointers-to-storage in handles, and partly because it could be very expensive so it might be better to be more explicit.

Member Function Documentation

◆ acquire_owning_identifier()

template<typename Storage , typename... Tags>
owning_identifier<Storage> neuron::container::soa< Storage, Tags >::acquire_owning_identifier ( )
inlineprivate

Create a new entry and return an identifier that owns it.

Calling this method increases size() by one. Destroying (modulo move operations) the returned identifier, which has the semantics of a unique_ptr, decreases size() by one.

Note that this has different semantics to standard library container methods such as emplace_back(), push_back(), insert() and so on. Because the returned identifier manages the lifetime of the newly-created entry, discarding the return value will cause the new entry to immediately be deleted.

This is a low-level call that is useful for the implementation of the owning_identifier template. The returned owning identifier is typically wrapped inside an owning handle type that adds data-structure-specific methods (e.g. v(), v_handle() for a Node).

Definition at line 1153 of file soa_container.hpp.

◆ apply_reverse_permutation() [1/2]

template<typename Storage , typename... Tags>
template<typename Arg >
frozen_token_type neuron::container::soa< Storage, Tags >::apply_reverse_permutation ( Arg &&  permutation)
inline

Permute the SoA-format data using an arbitrary range of integers.

Parameters
permutationThe reverse permutation vector to apply.
Returns
A token guaranteeing the frozen + sorted state of the container after the permutation was applied.

This will fail if the container is frozen.

Definition at line 1045 of file soa_container.hpp.

◆ apply_reverse_permutation() [2/2]

template<typename Storage , typename... Tags>
template<typename Range >
void neuron::container::soa< Storage, Tags >::apply_reverse_permutation ( Range  permutation,
frozen_token_type sorted_token 
)
inline

Permute the SoA-format data using an arbitrary range of integers.

Parameters
permutationThe reverse permutation vector to apply.
tokenA non-const token demonstrating that the caller is the only party that is forcing the container to be frozen, and (non-const) that they are authorised to transfer that status into this method

Definition at line 1059 of file soa_container.hpp.

◆ at()

template<typename Storage , typename... Tags>
non_owning_identifier<Storage> neuron::container::soa< Storage, Tags >::at ( std::size_t  offset) const
inline

Get a non-owning identifier to the offset-th entry.

This method should only be called if either: there is only one thread, or if a frozen token is held.

Definition at line 1195 of file soa_container.hpp.

◆ decrease_frozen_count()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::decrease_frozen_count ( )
inlineprivate

Flag that the storage is no longer frozen.

This is called from the destructor of state_token.

Definition at line 913 of file soa_container.hpp.

◆ empty()

template<typename Storage , typename... Tags>
bool neuron::container::soa< Storage, Tags >::empty ( ) const
inline

Test if the container is empty.

Note that this is not thread-safe if the container is not frozen, i.e. you should either hold a token showing the container is frozen, or you should ensure that no non-const operations on this container are being executed concurrently.

Definition at line 759 of file soa_container.hpp.

◆ erase()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::erase ( std::size_t  i)
inlineprivate

Remove the \(i^{\text{th}}\) row from the container.

This is currently implemented by swapping the last element into position \(i\) (if those are not the same element) and reducing the size by one. Iterators to the last element and the deleted element will be invalidated.

Definition at line 786 of file soa_container.hpp.

◆ field_active()

template<typename Storage , typename... Tags>
template<typename Tag >
bool neuron::container::soa< Storage, Tags >::field_active ( ) const
inline

Query whether the field associated with the given tag is active.

Definition at line 1525 of file soa_container.hpp.

◆ find_container_info()

template<typename Storage , typename... Tags>
std::unique_ptr<utils::storage_info> neuron::container::soa< Storage, Tags >::find_container_info ( void const *  cont) const
inline

Check if cont refers to a field in this container.

This is not intended to be called from multi-threaded code if the container is not frozen.

Definition at line 1450 of file soa_container.hpp.

◆ find_data_handle()

template<typename Storage , typename... Tags>
neuron::container::generic_data_handle neuron::container::soa< Storage, Tags >::find_data_handle ( neuron::container::generic_data_handle  input_handle) const
inline

Return a permutation-stable handle if ptr is inside us.

Todo:
Check const-correctness. Presumably a const version would return data_handle<T const>, which would hold a pointer-to-const for the container?

This is not intended to be called from multi-threaded code if the container is not frozen.

Definition at line 1380 of file soa_container.hpp.

◆ for_each_tag_vector_impl() [1/4]

template<typename Storage , typename... Tags>
template<detail::may_cause_reallocation might_reallocate, typename Callable , typename Tag , typename... RemainingTags>
Callable neuron::container::soa< Storage, Tags >::for_each_tag_vector_impl ( Callable  callable)
inlineprivate

Definition at line 851 of file soa_container.hpp.

◆ for_each_tag_vector_impl() [2/4]

template<typename Storage , typename... Tags>
template<detail::may_cause_reallocation , typename Callable >
Callable neuron::container::soa< Storage, Tags >::for_each_tag_vector_impl ( Callable  callable)
inlineprivate

Definition at line 858 of file soa_container.hpp.

◆ for_each_tag_vector_impl() [3/4]

template<typename Storage , typename... Tags>
template<typename Callable , typename Tag , typename... RemainingTags>
Callable neuron::container::soa< Storage, Tags >::for_each_tag_vector_impl ( Callable  callable) const
inlineprivate

Definition at line 884 of file soa_container.hpp.

◆ for_each_tag_vector_impl() [4/4]

template<typename Storage , typename... Tags>
template<typename Callable >
Callable neuron::container::soa< Storage, Tags >::for_each_tag_vector_impl ( Callable  callable) const
inlineprivate

Definition at line 891 of file soa_container.hpp.

◆ for_each_vector() [1/2]

template<typename Storage , typename... Tags>
template<detail::may_cause_reallocation might_reallocate, typename Callable >
Callable neuron::container::soa< Storage, Tags >::for_each_vector ( Callable  callable)
inlineprivate

Apply the given function to non-const versions of all vectors.

The callable has a signature compatible with:

void callable(const Tag& tag,
              std::vector<Tag::data_type, Allocator>& v,
              int field_index,
              int array_dim)

where array_dim is the array dimensions of the field field_index.

Template Parameters
might_reallocateMight the callable trigger reallocation of the vectors?
Parameters
callableCallable to invoke on each vector.

If might_allocate is true then the "cached" values of .data() for each vector will be updated.

Definition at line 839 of file soa_container.hpp.

◆ for_each_vector() [2/2]

template<typename Storage , typename... Tags>
template<typename Callable >
Callable neuron::container::soa< Storage, Tags >::for_each_vector ( Callable  callable) const
inlineprivate

Apply the given function to const-qualified versions of all vectors.

The callable has a signature compatible with:

void callable(const Tag& tag,
              const std::vector<Tag::data_type, Allocator>& v,
              int field_index,
              int array_dim)

where array_dim is the array dimensions of the field field_index.

Because of the const qualification this cannot cause reallocation and trigger updates of pointers inside m_data, so no might_reallocate parameter is needed.

Definition at line 878 of file soa_container.hpp.

◆ get() [1/2]

template<typename Storage , typename... Tags>
template<typename Tag >
Tag::type& neuron::container::soa< Storage, Tags >::get ( std::size_t  offset)
inline

Get the offset-th element of the column named by Tag.

Because this is returning a single value, it is permitted even when the container is frozen. The container being frozen means that operations that would invalidate iterators/pointers are forbidden, not that actual data values cannot change. Note that if the container is not frozen then care should be taken in a multi-threaded environment, as offset could be invalidated by operations performed by other threads (that would fail if the container were frozen).

Definition at line 1233 of file soa_container.hpp.

◆ get() [2/2]

template<typename Storage , typename... Tags>
template<typename Tag >
Tag::type const& neuron::container::soa< Storage, Tags >::get ( std::size_t  offset) const
inline

Get the offset-th element of the column named by Tag.

If the container is not frozen then care should be taken in a multi-threaded environment, as offset could be invalidated by operations performed by other threads (that would fail if the container were frozen).

Definition at line 1255 of file soa_container.hpp.

◆ get_array_dim_prefix_sums()

template<typename Storage , typename... Tags>
template<typename Tag >
int const* neuron::container::soa< Storage, Tags >::get_array_dim_prefix_sums ( ) const
inline

Get a pointer to an array holding the prefix sum of array dimensions for this tag.

Definition at line 1512 of file soa_container.hpp.

◆ get_array_dims() [1/2]

template<typename Storage , typename... Tags>
template<typename Tag >
int const* neuron::container::soa< Storage, Tags >::get_array_dims ( ) const
inline

Get a pointer to an array holding the array dimensions of the fields associated with this tag.

Definition at line 1493 of file soa_container.hpp.

◆ get_array_dims() [2/2]

template<typename Storage , typename... Tags>
template<typename Tag >
int neuron::container::soa< Storage, Tags >::get_array_dims ( int  field_index) const
inline

Definition at line 1498 of file soa_container.hpp.

◆ get_data_ptrs()

template<typename Storage , typename... Tags>
template<typename Tag >
Tag::type* const* neuron::container::soa< Storage, Tags >::get_data_ptrs ( ) const
inline

Get a pointer to a range of pointers that always point to the start of the contiguous storage.

Definition at line 1484 of file soa_container.hpp.

◆ get_field_instance() [1/2]

template<typename Storage , typename... Tags>
template<typename Tag >
Tag::type& neuron::container::soa< Storage, Tags >::get_field_instance ( std::size_t  offset,
int  field_index,
int  array_index = 0 
)
inline

Get the offset-th element of the field_index-th instance of the column named by Tag.

Put differently:

  • offset: index of a mechanism instance
  • field_index: index of a RANGE variable inside a mechanism
  • array_index: offset inside an array RANGE variable

Because this is returning a single value, it is permitted even when the container is frozen. The container being frozen means that operations that would invalidate iterators/pointers are forbidden, not that actual data values cannot change. Note that if the container is not frozen then care should be taken in a multi-threaded environment, as offset could be invalidated by operations performed by other threads (that would fail if the container were frozen).

Definition at line 1332 of file soa_container.hpp.

◆ get_field_instance() [2/2]

template<typename Storage , typename... Tags>
template<typename Tag >
Tag::type const& neuron::container::soa< Storage, Tags >::get_field_instance ( std::size_t  offset,
int  field_index,
int  array_index = 0 
) const
inline

Get the offset-th element of the field_index-th instance of the column named by Tag.

If the container is not frozen then care should be taken in a multi-threaded environment, as offset could be invalidated by operations performed by other threads (that would fail if the container were frozen).

Definition at line 1350 of file soa_container.hpp.

◆ get_field_instance_handle()

template<typename Storage , typename... Tags>
template<typename Tag >
data_handle<typename Tag::type> neuron::container::soa< Storage, Tags >::get_field_instance_handle ( non_owning_identifier_without_container  id,
int  field_index,
int  array_index = 0 
) const
inline

Get a handle to the given element of the field_index-th column named by Tag.

This is not intended to be called from multi-threaded code.

Definition at line 1301 of file soa_container.hpp.

◆ get_handle()

template<typename Storage , typename... Tags>
template<typename Tag >
data_handle<typename Tag::type> neuron::container::soa< Storage, Tags >::get_handle ( non_owning_identifier_without_container  id,
int  array_index = 0 
) const
inline

Get a handle to the given element of the column named by Tag.

This is not intended to be called from multi-threaded code, and might suffer from race conditions if the status of optional fields was being modified concurrently.

Definition at line 1276 of file soa_container.hpp.

◆ get_identifier()

template<typename Storage , typename... Tags>
non_owning_identifier_without_container neuron::container::soa< Storage, Tags >::get_identifier ( std::size_t  offset) const
inline

Get the offset-th identifier.

If the container is not frozen then care should be taken in a multi-threaded environment, as offset could be invalidated by operations performed by other threads (that would fail if the container were frozen).

Definition at line 1367 of file soa_container.hpp.

◆ get_num_variables()

template<typename Storage , typename... Tags>
template<typename Tag >
size_t neuron::container::soa< Storage, Tags >::get_num_variables ( ) const
inline

Definition at line 1504 of file soa_container.hpp.

◆ get_tag()

template<typename Storage , typename... Tags>
template<typename Tag >
constexpr Tag const& neuron::container::soa< Storage, Tags >::get_tag ( ) const
inlineconstexpr

Get the instance of the given tag type.

Template Parameters
TagThe tag type, which must be a member of the Tags... pack.
Returns
Const reference to the given tag type instance.

For example, if this is called on the Node::storage then Tag would be something like Node::field::Area, Node::field::RHS or Node::field::Voltage, which are empty types that serve to define the default values and types of those quantities.

At the time of writing the other possibility is that this is called on an instance of Mechanism::storage, in which case Tag must (currently) be Mechanism::field::FloatingPoint. This stores the names and array dimensions of the RANGE variables in the mechanism (MOD file), which are only known at runtime.

Definition at line 1214 of file soa_container.hpp.

◆ increase_frozen_count()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::increase_frozen_count ( )
inlineprivate

Record that a state_token was copied.

This should only be called from the copy constructor of a state_token, so m_frozen_count should already be non-zero.

Definition at line 902 of file soa_container.hpp.

◆ is_sorted()

template<typename Storage , typename... Tags>
bool neuron::container::soa< Storage, Tags >::is_sorted ( ) const
inline

Query if the underlying vectors are still "sorted".

See the documentation of issue_frozen_token() for an explanation of what this means. You most likely only want to call this method while holding a token guaranteeing that the container is frozen, and therefore that the sorted-status is fixed.

Definition at line 1032 of file soa_container.hpp.

◆ is_storage_pointer()

template<typename Storage , typename... Tags>
template<typename Tag >
bool neuron::container::soa< Storage, Tags >::is_storage_pointer ( typename Tag::type const *  ptr) const
inline

Query whether the given pointer-to-vector is the one associated to Tag.

Todo:
Fix this for tag types with num_variables()?

This is used so that one can ask a data_handle<T> if it refers to a particular field in a particular container. It is not intended to be called from multi-threaded code if the container is not frozen.

Definition at line 1431 of file soa_container.hpp.

◆ issue_frozen_token()

template<typename Storage , typename... Tags>
frozen_token_type neuron::container::soa< Storage, Tags >::issue_frozen_token ( )
inline

Create a token guaranteeing the container is in "frozen" state.

This does not modify the "sorted" flag on the container.

The token type is copy constructible but not default constructible. There is no need to check if a given instance of the token type is "valid"; if a token is held then the container is guaranteed to be frozen.

The tokens returned by this function are reference counted; the container will be frozen for as long as any token is alive.

Methods such as apply_reverse_permutation() take a non-const reference to one of these tokens. This is because a non-const token referring to a container with a token reference count of exactly one has an elevated status: the holder can lend it out to methods such as apply_reverse_permutation() to authorize specific pointer-invaliding operations. This is useful for implementing methods such as nrn_ensure_model_data_are_sorted() in a thread-safe way.

This method can be called from multiple threads, but note that doing so can have surprising effects w.r.t. the elevated status mentioned in the previous paragraph.

It is user-defined precisely what "sorted" means, but the soa<...> class makes some guarantees:

  • if the container is frozen, no pointers to elements in the underlying storage will be invalidated – attempts to do so will throw or abort.
  • if the container is not frozen, it will remain flagged as sorted until a potentially-pointer-invalidating operation (insertion, deletion) occurs, or mark_as_unsorted() is called. To mark a container as "sorted", apply an explicit permutation to it.

Note that "frozen" refers to the storage layout, not to the stored value, meaning that values inside a frozen container can still be modified – "frozen" is not "runtime const".

Todo:
A future extension could be to preserve the sorted flag until pointers are actually, not potentially, invalidated.

Definition at line 966 of file soa_container.hpp.

◆ mark_as_sorted()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::mark_as_sorted ( frozen_token_type write_token)
inline

Tell the container it is sorted.

Parameters
write_tokenNon-const token demonstrating the caller is the only token owner.

The meaning of being sorted is externally defined, so we should give external code the opportunity to say that the current order is OK. This probably only makes sense if the external code simply doesn't care about the ordering at all for some reason. This avoids having to construct a trivial permutation vector to achieve the same thing.

Definition at line 986 of file soa_container.hpp.

◆ mark_as_unsorted()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::mark_as_unsorted ( )
inline

Tell the container it is no longer sorted.

The meaning of being sorted is externally defined, and it is possible that some external change to an input of the (external) algorithm defining the sort order can mean that the data are no longer considered sorted, even if nothing has actually changed inside this container.

This method can only be called if the container is not frozen.

Definition at line 1005 of file soa_container.hpp.

◆ mark_as_unsorted_impl()

template<typename Storage , typename... Tags>
template<bool internal>
void neuron::container::soa< Storage, Tags >::mark_as_unsorted_impl ( )
inlineprivate

Set m_sorted = false and execute the callback.

Note
The caller is expected to hold m_mut when this is called.

Definition at line 1118 of file soa_container.hpp.

◆ memory_usage()

template<typename Storage , typename... Tags>
StorageMemoryUsage neuron::container::soa< Storage, Tags >::memory_usage ( ) const
inline

Definition at line 1542 of file soa_container.hpp.

◆ operator=() [1/2]

template<typename Storage , typename... Tags>
soa& neuron::container::soa< Storage, Tags >::operator= ( soa< Storage, Tags > &&  )
delete

soa is not move assignable

For the same reason it isn't movable.

◆ operator=() [2/2]

template<typename Storage , typename... Tags>
soa& neuron::container::soa< Storage, Tags >::operator= ( soa< Storage, Tags > const &  )
delete

soa is not copy assignable

For the same reasons it isn't copy constructible

◆ set_field_status()

template<typename Storage , typename... Tags>
template<typename... TagsToChange>
void neuron::container::soa< Storage, Tags >::set_field_status ( bool  enabled)
inline

Enable/disable the fields associated with the given tags.

Definition at line 1535 of file soa_container.hpp.

◆ set_unsorted_callback()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::set_unsorted_callback ( std::function< void()>  unsorted_callback)
inline

Set the callback that is invoked when the container becomes unsorted.

This is invoked by mark_as_unsorted() and when a container operation (insertion, permutation, deletion) causes the container to transition from being sorted to being unsorted.

This method is not thread-safe.

Definition at line 1020 of file soa_container.hpp.

◆ shrink_to_fit()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::shrink_to_fit ( )
inline

Definition at line 767 of file soa_container.hpp.

◆ size()

template<typename Storage , typename... Tags>
std::size_t neuron::container::soa< Storage, Tags >::size ( ) const
inline

Get the size of the container.

Note that this is not thread-safe if the container is not frozen, i.e. you should either hold a token showing the container is frozen, or you should ensure that no non-const operations on this container are being executed concurrently.

Definition at line 738 of file soa_container.hpp.

◆ throw_error()

template<typename Storage , typename... Tags>
void neuron::container::soa< Storage, Tags >::throw_error ( std::string_view  message) const
inlineprivate

Throw an exception with a pretty prefix.

Note
The caller is expected to hold m_mut when this is called.

Definition at line 1554 of file soa_container.hpp.

◆ translate_legacy_index()

template<typename Storage , typename... Tags>
template<typename Tag >
field_index neuron::container::soa< Storage, Tags >::translate_legacy_index ( int  legacy_index) const
inline

Definition at line 1517 of file soa_container.hpp.

Friends And Related Function Documentation

◆ owning_identifier< Storage >

template<typename Storage , typename... Tags>
friend struct owning_identifier< Storage >
friend

Definition at line 786 of file soa_container.hpp.

◆ state_token< Storage >

template<typename Storage , typename... Tags>
friend struct state_token< Storage >
friend

Definition at line 786 of file soa_container.hpp.

Member Data Documentation

◆ has_tag_v

template<typename Storage , typename... Tags>
template<typename Tag >
constexpr bool neuron::container::soa< Storage, Tags >::has_tag_v = detail::type_in_pack_v<Tag, Tags...>
staticconstexpr

Definition at line 1219 of file soa_container.hpp.

◆ m_data

template<typename Storage , typename... Tags>
std::tuple<detail::field_data<Tags, detail::field_impl_v<Tags> >...> neuron::container::soa< Storage, Tags >::m_data {}
private

Collection of data columns.

If the tag implements a num_variables() method then it is duplicated a runtime-determined number of times and get_field_instance<Tag>(i) returns the i-th element of the outer vector (of length num_variables()) of vectors. If is no num_variables() method then the outer vector can be omitted and get<Tag>() returns a vector of values.

Definition at line 1609 of file soa_container.hpp.

◆ m_frozen_count

template<typename Storage , typename... Tags>
std::size_t neuron::container::soa< Storage, Tags >::m_frozen_count {}
private

Reference count for tokens guaranteeing the container is frozen.

Definition at line 1593 of file soa_container.hpp.

◆ m_indices

template<typename Storage , typename... Tags>
std::vector<non_owning_identifier_without_container> neuron::container::soa< Storage, Tags >::m_indices {}
private

Pointers to identifiers that record the current physical row.

Definition at line 1598 of file soa_container.hpp.

◆ m_mut

template<typename Storage , typename... Tags>
std::mutex neuron::container::soa< Storage, Tags >::m_mut {}
mutableprivate

Mutex to protect m_frozen_count and m_sorted.

The frozen tokens are used to detect, possibly concurrent, use of incompatible operations, such as sorting while erasing rows. All operations that modify the structure of the container must happen sequentially.

To prevent a different thread from obtaining a frozen token while this thread is modifying structure of the container, this thread should lock m_mut. Likewise, any thread obtaining a frozen token, should acquire a lock on m_mut to ensure that there are no concurrent operations that require sequential access to the container.

By following this pattern the thread knows that the conditions related to sorted-ness and froze-ness of the container are valid for the entire duration of the operation (== member function of this class).

Note, enforcing proper sequencing of operations is left to the calling code. However, this mutex enforces the required thread-safety to be able to detect invalid concurrent access patterns.

Definition at line 1583 of file soa_container.hpp.

◆ m_sorted

template<typename Storage , typename... Tags>
bool neuron::container::soa< Storage, Tags >::m_sorted {false}
private

Flag for issue_frozen_token(), mark_as_unsorted() and is_sorted().

Definition at line 1588 of file soa_container.hpp.

◆ m_unsorted_callback

template<typename Storage , typename... Tags>
std::function<void()> neuron::container::soa< Storage, Tags >::m_unsorted_callback {}
private

Callback that is invoked when the container becomes unsorted.

Definition at line 1614 of file soa_container.hpp.

◆ tag_index_v

template<typename Storage , typename... Tags>
template<typename Tag >
constexpr std::size_t neuron::container::soa< Storage, Tags >::tag_index_v = detail::index_of_type_v<Tag, Tags...>
staticconstexprprivate

Definition at line 818 of file soa_container.hpp.


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