NEURON
model_data.hpp
Go to the documentation of this file.
1 #pragma once
7 
8 #include <optional>
9 #include <sstream>
10 
11 namespace neuron {
12 /** @brief Top-level structure.
13  *
14  * This level of indirection (as opposed to, for example, the Node data being a
15  * global variable in its own right) will give us more control over
16  * construction/destruction/... of different parts of the model data.
17  */
18 struct Model {
19  Model(); // defined in container.cpp
20  ~Model(); // defined in container.cpp
21 
22  /** @brief Access the structure containing the data of all Nodes.
23  */
25  return m_node_data;
26  }
27 
28  /** @brief Access the structure containing the data of all Nodes.
29  */
31  return m_node_data;
32  }
33 
34  /** @brief Apply a function to each non-null Mechanism.
35  */
36  template <typename Callable>
37  void apply_to_mechanisms(Callable const& callable) {
38  for (std::size_t type = 0; type < m_mech_data.size(); ++type) {
39  if (!m_mech_data[type]) {
40  continue;
41  }
42  callable(*m_mech_data[type]);
43  }
44  }
45 
46  template <typename Callable>
47  void apply_to_mechanisms(Callable const& callable) const {
48  for (std::size_t type = 0; type < m_mech_data.size(); ++type) {
49  if (!m_mech_data[type]) {
50  continue;
51  }
52  callable(*m_mech_data[type]);
53  }
54  }
55 
56  /**
57  * @brief Create a structure to hold the data of a new Mechanism.
58  */
59  template <typename... Args>
61  if (type >= m_mech_data.capacity()) {
62  m_mech_data.reserve(2 * m_mech_data.capacity());
63  }
64  if (type >= m_mech_data.size()) {
65  m_mech_data.resize(type + 1);
66  }
67  if (m_mech_data[type]) {
68  throw std::runtime_error("add_mechanism(" + std::to_string(type) +
69  "): storage already exists");
70  }
71  m_mech_data[type] =
72  std::make_unique<container::Mechanism::storage>(type, std::forward<Args>(args)...);
74  return *m_mech_data[type];
75  }
76 
77  /** @brief Destroy the structure holding the data of a particular mechanism.
78  */
79  void delete_mechanism(int type) {
80  if (type < 0 || std::size_t(type) >= m_mech_data.size() || !m_mech_data[type]) {
81  return;
82  }
83  if (std::size_t const size = m_mech_data[type]->size(); size > 0) {
84  throw std::runtime_error("delete_mechanism(" + std::to_string(type) +
85  "): refusing to delete storage that still hosts " +
86  std::to_string(size) + " instances");
87  }
88  m_mech_data[type].reset();
89  }
90 
91  /** @brief Get the structure holding the data of a particular Mechanism.
92  */
94  return mechanism_data_impl(type);
95  }
96 
97  /** @brief Get the structure holding the data of a particular Mechanism.
98  */
100  return mechanism_data_impl(type);
101  }
102 
103  [[nodiscard]] std::size_t mechanism_storage_size() const {
104  return m_mech_data.size();
105  }
106 
107  [[nodiscard]] bool is_valid_mechanism(int type) const {
108  return 0 <= type && std::size_t(type) < mechanism_storage_size() && m_mech_data[type];
109  }
110 
111  /**
112  * @brief Find some metadata about the given container.
113  *
114  * The argument type will typically be a T* that contains the result of calling .data() on some
115  * vector in the global model data structure.
116  */
117  [[nodiscard]] std::unique_ptr<container::utils::storage_info> find_container_info(
118  void const* cont) const;
119 
120  void shrink_to_fit() {
122  apply_to_mechanisms([](auto& mech_data) { mech_data.shrink_to_fit(); });
123  }
124 
125  private:
127  if (type < 0 || std::size_t(type) >= m_mech_data.size()) {
128  throw std::runtime_error("mechanism_data(" + std::to_string(type) +
129  "): type out of range");
130  }
131  const auto& data_ptr = m_mech_data[type];
132  if (!data_ptr) {
133  throw std::runtime_error("mechanism_data(" + std::to_string(type) +
134  "): data for type was null");
135  }
136 
137  return *data_ptr;
138  }
139 
140 
142 
143  /** @brief One structure for all Nodes.
144  */
146 
147  /** @brief Storage for mechanism-specific data.
148  *
149  * Each element is allocated on the heap so that reallocating this vector
150  * does not invalidate pointers to container::Mechanism::storage.
151  */
152  std::vector<std::unique_ptr<container::Mechanism::storage>> m_mech_data{};
153 
154  /**
155  * @brief Backing storage for defer_delete helper.
156  */
157  std::vector<void*> m_ptrs_for_deferred_deletion{};
158 };
159 
163  : node_data_token{std::move(node_data_token_)}
164  , m_cache{cache} {}
165  [[nodiscard]] cache::Model& cache() {
166  return m_cache;
167  }
168  [[nodiscard]] cache::Model const& cache() const {
169  return m_cache;
170  }
172  m_cache = cache;
173  }
174  [[nodiscard]] cache::Mechanism& mech_cache(std::size_t i) {
175  return cache().mechanism.at(i);
176  }
177  [[nodiscard]] cache::Mechanism const& mech_cache(std::size_t i) const {
178  return cache().mechanism.at(i);
179  }
180  [[nodiscard]] cache::Thread& thread_cache(std::size_t i) {
181  return cache().thread.at(i);
182  }
183  [[nodiscard]] cache::Thread const& thread_cache(std::size_t i) const {
184  return cache().thread.at(i);
185  }
187  std::vector<container::Mechanism::storage::frozen_token_type> mech_data_tokens{};
188 
189  private:
190  std::reference_wrapper<cache::Model> m_cache;
191 };
192 
193 namespace detail {
194 // Defining this inline seems to lead to duplicate copies when we dlopen
195 // libnrnmech.so , so we define it explicitly in container.cpp as part of
196 // libnrniv.so
197 extern Model model_data;
198 } // namespace detail
199 
200 /** @brief Access the global Model instance.
201  *
202  * Just to be going on with. Needs more thought about who actually holds/owns
203  * the structures that own the SOA data. Could use a static local if we need to
204  * control/defer when this is constructed.
205  */
206 inline Model& model() {
207  return detail::model_data;
208 }
209 
210 namespace container {
212 }
213 
214 } // namespace neuron
#define i
Definition: md1redef.h:19
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:200
cache::ModelMemoryUsage memory_usage(const std::optional< neuron::cache::Model > &model)
Model model_data
Definition: container.cpp:56
In mechanism libraries, cannot use auto const token = nrn_ensure_model_data_are_sorted(); because the...
Definition: tnode.hpp:17
Model & model()
Access the global Model instance.
Definition: model_data.hpp:206
std::string to_string(const T &obj)
short type
Definition: cabvars.h:10
Top-level structure.
Definition: model_data.hpp:18
void delete_mechanism(int type)
Destroy the structure holding the data of a particular mechanism.
Definition: model_data.hpp:79
std::unique_ptr< container::utils::storage_info > find_container_info(void const *cont) const
Find some metadata about the given container.
Definition: container.cpp:29
void shrink_to_fit()
Definition: model_data.hpp:120
std::vector< void * > m_ptrs_for_deferred_deletion
Backing storage for defer_delete helper.
Definition: model_data.hpp:157
container::Mechanism::storage & add_mechanism(int type, Args &&... args)
Create a structure to hold the data of a new Mechanism.
Definition: model_data.hpp:60
bool is_valid_mechanism(int type) const
Definition: model_data.hpp:107
container::Mechanism::storage const & mechanism_data(int type) const
Get the structure holding the data of a particular Mechanism.
Definition: model_data.hpp:99
void set_unsorted_callback(container::Mechanism::storage &mech_data)
Definition: container.cpp:44
std::vector< std::unique_ptr< container::Mechanism::storage > > m_mech_data
Storage for mechanism-specific data.
Definition: model_data.hpp:152
container::Mechanism::storage & mechanism_data(int type)
Get the structure holding the data of a particular Mechanism.
Definition: model_data.hpp:93
container::Node::storage const & node_data() const
Access the structure containing the data of all Nodes.
Definition: model_data.hpp:30
container::Node::storage m_node_data
One structure for all Nodes.
Definition: model_data.hpp:145
void apply_to_mechanisms(Callable const &callable)
Apply a function to each non-null Mechanism.
Definition: model_data.hpp:37
container::Node::storage & node_data()
Access the structure containing the data of all Nodes.
Definition: model_data.hpp:24
container::Mechanism::storage & mechanism_data_impl(int type) const
Definition: model_data.hpp:126
std::size_t mechanism_storage_size() const
Definition: model_data.hpp:103
void apply_to_mechanisms(Callable const &callable) const
Definition: model_data.hpp:47
std::vector< Mechanism > mechanism
Definition: model_data.hpp:38
std::vector< Thread > thread
Definition: model_data.hpp:37
Underlying storage for all instances of a particular Mechanism.
Memory usage of a neuron::Model.
Underlying storage for all Nodes.
Definition: node_data.hpp:17
Token whose lifetime manages the frozen state of a container.
model_sorted_token(cache::Model &cache, container::Node::storage::frozen_token_type node_data_token_)
Definition: model_data.hpp:161
std::vector< container::Mechanism::storage::frozen_token_type > mech_data_tokens
Definition: model_data.hpp:187
container::Node::storage::frozen_token_type node_data_token
Definition: model_data.hpp:186
cache::Thread & thread_cache(std::size_t i)
Definition: model_data.hpp:180
cache::Model const & cache() const
Definition: model_data.hpp:168
cache::Model & cache()
Definition: model_data.hpp:165
void set_cache(cache::Model &&cache)
Definition: model_data.hpp:171
cache::Mechanism const & mech_cache(std::size_t i) const
Definition: model_data.hpp:177
cache::Thread const & thread_cache(std::size_t i) const
Definition: model_data.hpp:183
std::reference_wrapper< cache::Model > m_cache
Definition: model_data.hpp:190
cache::Mechanism & mech_cache(std::size_t i)
Definition: model_data.hpp:174