Grail (C++)  1.1.1
A multi-platform, modular, universal engine for embedding advanced AI in games.
Blackboard.hh
1 #ifndef GRAIL_BLACKBOARD_H
2 #define GRAIL_BLACKBOARD_H
3 
4 #include "consts.h"
5 #include "../GrailLogger/LoggerManager.hh"
6 
7 #include <functional>
8 #include <map>
9 #include <mutex>
10 
11 #ifndef BUILD_UNREAL
12 #include <any>
13 #endif
14 
15 namespace grail
16 {
20  class Blackboard
21  {
22  #ifdef BUILD_UNREAL
23  class UnsafeAny;
24  friend bool operator == (const UnsafeAny& first, const UnsafeAny& second);
25  #endif
26 
27  public:
28  Blackboard() = default;
29  Blackboard(const Blackboard& other);
30  Blackboard(Blackboard&& other) = delete;
31 
32  ~Blackboard() = default;
33 
34  Blackboard& operator =(const Blackboard& other);
35  Blackboard& operator =(Blackboard&& other) = delete;
36 
44  #ifndef BUILD_UNREAL
45  static void TwoWayMerge(Blackboard& first,
46  Blackboard& second,
47  std::function<const std::any&(const std::any&, const std::any&)> firstStrategy =
49  std::function<const std::any&(const std::any&, const std::any&)> secondStrategy =
50  OursStrategy);
51  #else
52  static void TwoWayMerge(Blackboard& first, Blackboard& second,
53  std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> firstStrategy = OursStrategy,
54  std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> secondStrategy = OursStrategy);
55  #endif
56 
63  #ifndef BUILD_UNREAL
64  static const std::any& OursStrategy(const std::any& ours, const std::any& theirs);
65  #else
66  static const UnsafeAny& OursStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
67  #endif
68 
75  #ifndef BUILD_UNREAL
76  static const std::any& TheirsStrategy(const std::any& ours, const std::any& theirs);
77  #else
78  static const UnsafeAny& TheirsStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
79  #endif
80 
86  #ifndef BUILD_UNREAL
87  void Merge(const Blackboard& other,
88  std::function<const std::any&(const std::any&, const std::any&)> mergeStrategy = OursStrategy);
89  #else
90  void Merge(const Blackboard& other, std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> mergeStrategy = OursStrategy);
91  #endif
92 
97  void RemoveEntry(const std::string& key);
98 
104  bool ContainsKey(const std::string& key) const;
105 
110  size_t Size() const;
111 
112  template <typename T>
118  void SetValue(const std::string& key, const T& value)
119  {
120  std::lock_guard<std::mutex> lock{mutex};
121  #ifndef BUILD_UNREAL
122  std::any any = value;
123  data[key] = any;
124  #else
125  auto deleter = [](void* memory)
126  {
127  T* dataPointer = static_cast<T*>(memory);
128  delete dataPointer;
129  };
130  auto cloner = [](void* memory)
131  {
132  T* dataPointer = static_cast<T*>(memory);
133  return new T{*dataPointer};
134  };
135 
136  data[key] = UnsafeAny(new T{value}, deleter, cloner);
137  #endif
138  }
139 
140  template <typename T, std::enable_if_t<!std::is_reference<T>::value>* = nullptr>
146  void SetValue(const std::string& key, T&& value)
147  {
148  std::lock_guard<std::mutex> lock{mutex};
149  #ifndef BUILD_UNREAL
150  data[key] = std::any{value};
151  #else
152  auto deleter = [](void* memory)
153  {
154  T* dataPointer = static_cast<T*>(memory);
155  delete dataPointer;
156  };
157  auto cloner = [](void* memory)
158  {
159  T* dataPointer = static_cast<T*>(memory);
160  return new T{*dataPointer};
161  };
162  data[key] = UnsafeAny(new T{value}, deleter, cloner);
163  #endif
164  }
165 
166  template <typename T>
171  void SetDefaultValue(const std::string& key)
172  {
173  std::lock_guard<std::mutex> lock{mutex};
174  #ifndef BUILD_UNREAL
175  data[key] = std::any{T{}};
176  #else
177  auto deleter = [](void* memory)
178  {
179  T* dataPointer = static_cast<T*>(memory);
180  delete dataPointer;
181  };
182  auto cloner = [](void* memory)
183  {
184  T* dataPointer = static_cast<T*>(memory);
185  return new T{*dataPointer};
186  };
187  data[key] = UnsafeAny(new T{}, deleter, cloner);
188  #endif
189  }
190 
191  template <typename T>
197  const T& GetValue(const std::string& key) const
198  {
199  std::lock_guard<std::mutex> lock{mutex};
200  auto iterator = data.find(key);
201  if(iterator == data.end())
202  {
203  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, Severity::CRITICAL, "Invalid key (" + key + ")");
204  }
205  #ifndef BUILD_UNREAL
206  return std::any_cast<const T&>(iterator->second);
207  #else
208  return *static_cast<T*>(iterator->second.GetDataPointer());
209  #endif
210  }
211 
212  template <typename T>
218  T& GetOrAddValue(const std::string& key)
219  {
220  std::lock_guard<std::mutex> lock{mutex};
221  #ifndef BUILD_UNREAL
222  return std::any_cast<T&>(data[key]);
223  #else
224  auto iterator = data.find(key);
225  if(iterator == data.end())
226  {
227  auto deleter = [](void* memory)
228  {
229  T* dataPointer = static_cast<T*>(memory);
230  delete dataPointer;
231  };
232  auto cloner = [](void* memory)
233  {
234  T* dataPointer = static_cast<T*>(memory);
235  return new T{*dataPointer};
236  };
237  iterator = data.emplace(std::piecewise_construct, std::forward_as_tuple(key),
238  std::forward_as_tuple(new T{}, deleter, cloner)).first;
239  }
240  return *static_cast<T*>(iterator->second.GetDataPointer());
241  #endif
242  }
243 
244  template <typename T>
251  bool TryGetValue(const std::string& key, T& outValue) const
252  {
253  std::lock_guard<std::mutex> lock{mutex};
254  auto iter = data.find(key);
255  if(iter != data.end())
256  {
257  #ifndef BUILD_UNREAL
258  outValue = std::any_cast<T>(iter->second);
259  #else
260  outValue = *static_cast<T*>(iter->second.GetDataPointer());
261  #endif
262  return true;
263  }
264  return false;
265  }
266 
267  void AddDataToNameMap(std::map<std::string, std::string>& outMap) const;
268 
269  private:
270  #ifndef BUILD_UNREAL
271  std::map<std::string, std::any> data{};
272  #else
273  class UnsafeAny
274  {
275  friend bool operator == (const UnsafeAny& first, const UnsafeAny& second);
276 
277  public:
278  UnsafeAny() = default;
279  UnsafeAny(void* dataPointer, std::function<void(void*)> deleter, std::function<void*(void*)> cloner);
280 
281  UnsafeAny(const UnsafeAny& other);
282  UnsafeAny(UnsafeAny&& other);
283 
284  ~UnsafeAny();
285 
286  UnsafeAny& operator = (const UnsafeAny& other);
287  UnsafeAny& operator = (UnsafeAny&& other);
288 
289  void* GetDataPointer() const;
290 
291  private:
292  void* dataPointer{nullptr};
293  std::function<void(void*)> deleter{[](void*){}};
294  std::function<void*(void*)> cloner{[](void*){ return nullptr; }};
295  };
296 
297  std::map<std::string, UnsafeAny> data{};
298  #endif
299  mutable std::mutex mutex{};
300  };
301 }
302 
303 #endif //GRAIL_BLACKBOARD_H
grail::Blackboard::Size
size_t Size() const
Size.
Definition: Blackboard.cpp:97
grail::Blackboard::TryGetValue
bool TryGetValue(const std::string &key, T &outValue) const
TryGetValue - Checks whether blackboard contains given key. If it does, assigns keyed value to refere...
Definition: Blackboard.hh:251
grail::Blackboard::TheirsStrategy
static const std::any & TheirsStrategy(const std::any &ours, const std::any &theirs)
TheirsStrategy.
Definition: Blackboard.cpp:45
grail::Blackboard::SetDefaultValue
void SetDefaultValue(const std::string &key)
SetDefaultValue - Inserts default value of given type keyed with name into this blackboard....
Definition: Blackboard.hh:171
grail::Blackboard
The Blackboard class - grail's universal data container.
Definition: Blackboard.hh:20
grail::Blackboard::ContainsKey
bool ContainsKey(const std::string &key) const
ContainsKey - Checks whether this blackboard contains given key.
Definition: Blackboard.cpp:91
grail::Blackboard::SetValue
void SetValue(const std::string &key, const T &value)
SetValue - Inserts value keyed with name into this blackboard. If key already exists new value is ass...
Definition: Blackboard.hh:118
grail::Blackboard::RemoveEntry
void RemoveEntry(const std::string &key)
RemoveValue - Deletes value keyed with given name from this blackboard.
Definition: Blackboard.cpp:85
grail::Blackboard::OursStrategy
static const std::any & OursStrategy(const std::any &ours, const std::any &theirs)
OursStrategy.
Definition: Blackboard.cpp:36
grail::Blackboard::Merge
void Merge(const Blackboard &other, std::function< const std::any &(const std::any &, const std::any &)> mergeStrategy=OursStrategy)
Merge - Merges data from other blackboard into this one. All conflicts are solved in favor of other b...
Definition: Blackboard.cpp:54
grail::Blackboard::GetOrAddValue
T & GetOrAddValue(const std::string &key)
GetOrAddValue - Returns value keyed with name. If blackboard does not contain key,...
Definition: Blackboard.hh:218
grail::Blackboard::SetValue
void SetValue(const std::string &key, T &&value)
SetValue - Inserts value keyed with name into this blackboard. If key already exists new value is ass...
Definition: Blackboard.hh:146
grail::Blackboard::TwoWayMerge
static void TwoWayMerge(Blackboard &first, Blackboard &second, std::function< const std::any &(const std::any &, const std::any &)> firstStrategy=OursStrategy, std::function< const std::any &(const std::any &, const std::any &)> secondStrategy=OursStrategy)
TwoWayMerge - merges second blackboard into first and first into second, uses provided merge strategi...
Definition: Blackboard.cpp:21
grail::Blackboard::GetValue
const T & GetValue(const std::string &key) const
GetValue - Returns value keyed with name. This method assumes that this blackboard contains given key...
Definition: Blackboard.hh:197