BioDynaMo  v1.05.120-25dc9790
agent_pointer.h
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
15 #ifndef CORE_AGENT_AGENT_POINTER_H_
16 #define CORE_AGENT_AGENT_POINTER_H_
17 
18 #include <cstdint>
19 #include <limits>
20 #include <ostream>
21 #include <type_traits>
22 
23 #include "core/agent/agent_uid.h"
25 #include "core/simulation.h"
26 #include "core/util/root.h"
27 
28 namespace bdm {
29 
30 class Agent;
31 
48 
57 template <typename TAgent = Agent>
58 class AgentPointer {
59  public:
60  explicit AgentPointer(const AgentUid& uid) {
61  if (uid == AgentUid()) {
62  *this = nullptr;
63  return;
64  }
66  d_.uid = uid;
67  } else {
69  d_.agent = Cast<Agent, TAgent>(ctxt->GetAgent(uid));
70  }
71  }
72  explicit AgentPointer(TAgent* agent) {
73  if (!agent) {
74  *this = nullptr;
75  }
77  d_.uid = agent->GetUid();
78  } else {
79  d_.agent = agent;
80  }
81  }
82 
84  AgentPointer(std::nullptr_t) { *this = nullptr; }
85 
87  AgentPointer() { *this = nullptr; }
88 
89  ~AgentPointer() = default;
90 
91  uint64_t GetUidAsUint64() const {
92  if (*this == nullptr) {
93  return AgentUid();
94  }
96  return d_.uid;
97  } else {
98  return d_.agent->GetUid();
99  }
100  }
101 
102  AgentUid GetUid() const {
103  if (*this == nullptr) {
104  return AgentUid();
105  }
107  return d_.uid;
108  } else {
109  return d_.agent->GetUid();
110  }
111  }
112 
115  bool operator==(std::nullptr_t) const {
117  return d_.uid == AgentUid();
118  } else {
119  return d_.agent == nullptr;
120  }
121  }
122 
125  bool operator!=(std::nullptr_t) const { return !this->operator==(nullptr); }
126 
127  bool operator==(const AgentPointer& other) const {
129  return d_.uid == other.d_.uid;
130  } else {
131  return d_.agent == other.d_.agent;
132  }
133  }
134 
135  bool operator!=(const AgentPointer& other) const {
137  return d_.uid != other.d_.uid;
138  } else {
139  return d_.agent != other.d_.agent;
140  }
141  }
142 
143  template <typename TOtherAgent>
144  bool operator==(const TOtherAgent* other) const {
146  if (other) {
147  return d_.uid == other->GetUid();
148  } else {
149  return d_.uid == AgentUid();
150  }
151  } else {
152  if (d_.agent != nullptr && other != nullptr) {
153  return d_.agent->GetUid() == other->GetUid();
154  } else if (d_.agent == nullptr && other == nullptr) {
155  return true;
156  } else {
157  return false;
158  }
159  }
160  }
161 
162  template <typename TOtherAgent>
163  bool operator!=(const TOtherAgent* other) const {
164  return !this->operator==(other);
165  }
166 
169  AgentPointer& operator=(std::nullptr_t) {
171  d_.uid = AgentUid();
172  } else {
173  d_.agent = nullptr;
174  }
175  return *this;
176  }
177 
178  TAgent* operator->() {
179  assert(*this != nullptr);
181  if (d_.uid == AgentUid()) {
182  return nullptr;
183  }
184  auto* ctxt = Simulation::GetActive()->GetExecutionContext();
185  return Cast<Agent, TAgent>(ctxt->GetAgent(d_.uid));
186  } else {
187  return d_.agent;
188  }
189  }
190 
191  const TAgent* operator->() const {
192  assert(*this != nullptr);
194  if (d_.uid == AgentUid()) {
195  return nullptr;
196  }
197  auto* ctxt = Simulation::GetActive()->GetExecutionContext();
198  return Cast<const Agent, const TAgent>(ctxt->GetConstAgent(d_.uid));
199  } else {
200  return d_.agent;
201  }
202  }
203 
204  friend std::ostream& operator<<(std::ostream& str,
205  const AgentPointer& agent_ptr) {
206  str << "{ uid: " << agent_ptr.GetUid() << "}";
207  return str;
208  }
209 
210  TAgent& operator*() { return *(this->operator->()); }
211 
212  const TAgent& operator*() const { return *(this->operator->()); }
213 
214  operator bool() const { return *this != nullptr; } // NOLINT
215 
216  operator AgentPointer<Agent>() const {
218  return AgentPointer<Agent>(d_.uid);
219  } else {
220  return AgentPointer<Agent>(Cast<TAgent, Agent>(d_.agent));
221  }
222  }
223 
224  TAgent* Get() { return this->operator->(); }
225 
226  const TAgent* Get() const { return this->operator->(); }
227 
228  bool operator<(const AgentPointer& other) const {
230  return d_.uid < other.d_.uid;
231  } else {
232  return d_.agent < other.d_.agent;
233  }
234  }
235 
237  union Data {
239  TAgent* agent;
240  };
241 
242  private:
243  Data d_ = {AgentUid()};
244 
245  template <typename TFrom, typename TTo>
246  typename std::enable_if<std::is_base_of<TFrom, TTo>::value, TTo*>::type Cast(
247  TFrom* agent) const {
248  return static_cast<TTo*>(agent);
249  }
250 
251  template <typename TFrom, typename TTo>
252  typename std::enable_if<!std::is_base_of<TFrom, TTo>::value, TTo*>::type Cast(
253  TFrom* agent) const {
254  return dynamic_cast<TTo*>(agent);
255  }
256 
258 };
259 
260 // The following custom streamer should be visible to rootcling for dictionary
261 // generation, but not to the interpreter!
262 #if (!defined(__CLING__) || defined(__ROOTCLING__)) && defined(USE_DICT)
263 
264 template <typename TAgent>
265 inline void AgentPointer<TAgent>::Streamer(TBuffer& R__b) {
266  if (R__b.IsReading()) {
267  R__b.ReadClassBuffer(AgentPointer::Class(), this);
268  AgentUid restored_uid;
269  R__b.ReadClassBuffer(AgentUid::Class(), &restored_uid);
271  d_.uid = restored_uid;
272  } else if (restored_uid != AgentUid()) {
273  auto* ctxt = Simulation::GetActive()->GetExecutionContext();
274  d_.agent = Cast<Agent, TAgent>(ctxt->GetAgent(restored_uid));
275  } else {
276  d_.agent = nullptr;
277  }
278  } else {
279  R__b.WriteClassBuffer(AgentPointer::Class(), this);
280  AgentUid uid;
282  uid = d_.uid;
283  R__b.WriteClassBuffer(AgentUid::Class(), &d_.uid);
284  } else if (d_.agent != nullptr) {
285  uid = d_.agent->GetUid();
286  }
287  R__b.WriteClassBuffer(AgentUid::Class(), &uid);
288  }
289 }
290 
291 #endif // !defined(__CLING__) || defined(__ROOTCLING__)
292 
293 template <typename T>
294 struct is_agent_ptr { // NOLINT
295  static constexpr bool value = false; // NOLINT
296 };
297 
298 template <typename T>
299 struct is_agent_ptr<AgentPointer<T>> { // NOLINT
300  static constexpr bool value = true; // NOLINT
301 };
302 
303 namespace detail {
304 
305 struct ExtractUid {
306  template <typename T>
307  static typename std::enable_if<is_agent_ptr<T>::value, uint64_t>::type GetUid(
308  const T& t) {
309  return t.GetUid();
310  }
311 
312  template <typename T>
313  static typename std::enable_if<!is_agent_ptr<T>::value, uint64_t>::type
314  GetUid(const T& t) {
315  return 0; // std::numeric_limits<uint64_t>::max();
316  }
317 };
318 
319 } // namespace detail
320 
321 } // namespace bdm
322 
323 #endif // CORE_AGENT_AGENT_POINTER_H_
bdm::AgentPointer::Cast
std::enable_if< std::is_base_of< TFrom, TTo >::value, TTo * >::type Cast(TFrom *agent) const
Definition: agent_pointer.h:246
bdm::AgentPointer::BDM_CLASS_DEF_NV
BDM_CLASS_DEF_NV(AgentPointer, 3)
bdm::detail::ExtractUid::GetUid
static std::enable_if< is_agent_ptr< T >::value, uint64_t >::type GetUid(const T &t)
Definition: agent_pointer.h:307
agent_uid.h
bdm::AgentPointer::GetUidAsUint64
uint64_t GetUidAsUint64() const
Definition: agent_pointer.h:91
bdm
Definition: agent.cc:39
bdm::detail::ExtractUid::GetUid
static std::enable_if<!is_agent_ptr< T >::value, uint64_t >::type GetUid(const T &t)
Definition: agent_pointer.h:314
bdm::AgentPointer
Definition: agent_pointer.h:58
bdm::AgentPointer::Get
TAgent * Get()
Definition: agent_pointer.h:224
bdm::AgentPointer::Cast
std::enable_if<!std::is_base_of< TFrom, TTo >::value, TTo * >::type Cast(TFrom *agent) const
Definition: agent_pointer.h:252
bdm::AgentPointer::operator<<
friend std::ostream & operator<<(std::ostream &str, const AgentPointer &agent_ptr)
Definition: agent_pointer.h:204
bdm::AgentPointer::operator==
bool operator==(std::nullptr_t) const
Definition: agent_pointer.h:115
execution_context.h
bdm::AgentPointer::operator*
TAgent & operator*()
Definition: agent_pointer.h:210
bdm::AgentPointer::~AgentPointer
~AgentPointer()=default
bdm::AgentPointer::AgentPointer
AgentPointer(std::nullptr_t)
Allow AgentPointer<> ap = nullptr definitions.
Definition: agent_pointer.h:84
bdm::AgentPointer::operator->
const TAgent * operator->() const
Definition: agent_pointer.h:191
bdm::AgentPointer::Data
TODO. Replace with std::variant once we move to >= c++17.
Definition: agent_pointer.h:237
bdm::AgentPointer::AgentPointer
AgentPointer()
constructs an AgentPointer object representing a nullptr
Definition: agent_pointer.h:87
bdm::AgentPointer::Get
const TAgent * Get() const
Definition: agent_pointer.h:226
bdm::AgentPointer::operator<
bool operator<(const AgentPointer &other) const
Definition: agent_pointer.h:228
bdm::AgentPointer::operator!=
bool operator!=(const AgentPointer &other) const
Definition: agent_pointer.h:135
bdm::AgentPointer::operator->
TAgent * operator->()
Definition: agent_pointer.h:178
bdm::AgentPointer::operator!=
bool operator!=(std::nullptr_t) const
Definition: agent_pointer.h:125
bdm::detail::ExtractUid
Definition: agent_pointer.h:305
bdm::is_agent_ptr::value
static constexpr bool value
Definition: agent_pointer.h:295
bdm::kIndirect
@ kIndirect
Definition: agent_pointer.h:42
root.h
bdm::gAgentPointerMode
AgentPointerMode gAgentPointerMode
Definition: agent_pointer.cc:19
bdm::AgentPointer::AgentPointer
AgentPointer(TAgent *agent)
Definition: agent_pointer.h:72
bdm::AgentPointer::Data::agent
TAgent * agent
Definition: agent_pointer.h:239
bdm::AgentPointer::operator==
bool operator==(const TOtherAgent *other) const
Definition: agent_pointer.h:144
bdm::AgentPointer::operator=
AgentPointer & operator=(std::nullptr_t)
Definition: agent_pointer.h:169
bdm::AgentPointer::GetUid
AgentUid GetUid() const
Definition: agent_pointer.h:102
bdm::AgentUid
Definition: agent_uid.h:25
bdm::AgentPointer::operator*
const TAgent & operator*() const
Definition: agent_pointer.h:212
bdm::Simulation::GetExecutionContext
ExecutionContext * GetExecutionContext()
Returns a thread local execution context.
Definition: simulation.cc:271
bdm::AgentPointer::operator!=
bool operator!=(const TOtherAgent *other) const
Definition: agent_pointer.h:163
simulation.h
bdm::AgentPointer::d_
Data d_
Definition: agent_pointer.h:243
bdm::AgentPointerMode
AgentPointerMode
Definition: agent_pointer.h:42
bdm::Simulation::GetActive
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
Definition: simulation.cc:68
bdm::AgentPointer::AgentPointer
AgentPointer(const AgentUid &uid)
Definition: agent_pointer.h:60
bdm::kDirect
@ kDirect
Definition: agent_pointer.h:42
bdm::is_agent_ptr
Definition: agent_pointer.h:294
bdm::AgentPointer::Data::uid
AgentUid uid
Definition: agent_pointer.h:238
bdm::AgentPointer::operator==
bool operator==(const AgentPointer &other) const
Definition: agent_pointer.h:127