(C++)  1.0.0
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 "Logger/LoggerManager.hh"
6 
7 #include <map>
8 #include <mutex>
9 #include <functional>
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();
29  Blackboard(const Blackboard& other);
30  Blackboard(Blackboard&& other) = delete;
31 
32  ~Blackboard();
33 
34  Blackboard& operator = (const Blackboard& other);
35  Blackboard& operator = (Blackboard&& other) = delete;
36 
44 #ifndef BUILD_UNREAL
45  static void TwoWayMerge(Blackboard& first, Blackboard& second,
46  std::function<const std::any&(const std::any&, const std::any&)> firstStrategy = OursStrategy,
47  std::function<const std::any&(const std::any&, const std::any&)> secondStrategy = OursStrategy);
48 #else
49  static void TwoWayMerge(Blackboard& first, Blackboard& second,
50  std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> firstStrategy = OursStrategy,
51  std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> secondStrategy = OursStrategy);
52 #endif
59 #ifndef BUILD_UNREAL
60  static const std::any& OursStrategy(const std::any& ours, const std::any& theirs);
61 #else
62  static const UnsafeAny& OursStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
63 #endif
64 
71 #ifndef BUILD_UNREAL
72  static const std::any& TheirsStrategy(const std::any& ours, const std::any& theirs);
73 #else
74  static const UnsafeAny& TheirsStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
75 #endif
76 
82 #ifndef BUILD_UNREAL
83  void Merge(const Blackboard& other, std::function<const std::any&(const std::any&, const std::any&)> mergeStrategy = OursStrategy);
84 #else
85  void Merge(const Blackboard& other, std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> mergeStrategy = OursStrategy);
86 #endif
87 
92  void RemoveEntry(const std::string& key);
93 
99  bool ContainsKey(const std::string& key) const;
100 
105  size_t Size() const;
106 
107 
108  template<typename T>
114  void SetValue(const std::string& key, const T& value)
115  {
116  std::lock_guard<std::mutex> lock{mutex};
117 #ifndef BUILD_UNREAL
118  std::any any = value;
119  data[key] = any;
120 #else
121  auto deleter = [](void* memory)
122  {
123  T* dataPointer = static_cast<T*>(memory);
124  delete dataPointer;
125  };
126  auto cloner = [](void* memory)
127  {
128  T* dataPointer = static_cast<T*>(memory);
129  return new T{*dataPointer};
130  };
131 
132  data[key] = UnsafeAny(new T{value}, deleter, cloner);
133 #endif
134  }
135 
136  template<typename T, std::enable_if_t<!std::is_reference<T>::value>* = nullptr>
142  void SetValue(const std::string& key, T&& value)
143  {
144  std::lock_guard<std::mutex> lock{mutex};
145 #ifndef BUILD_UNREAL
146  data[key] = std::any{value};
147 #else
148  auto deleter = [](void* memory)
149  {
150  T* dataPointer = static_cast<T*>(memory);
151  delete dataPointer;
152  };
153  auto cloner = [](void* memory)
154  {
155  T* dataPointer = static_cast<T*>(memory);
156  return new T{*dataPointer};
157  };
158  data[key] = UnsafeAny(new T{value}, deleter, cloner);
159 #endif
160  }
161 
162  template<typename T>
167  void SetDefaultValue(const std::string& key)
168  {
169  std::lock_guard<std::mutex> lock{mutex};
170 #ifndef BUILD_UNREAL
171  data[key] = std::any{T{}};
172 #else
173  auto deleter = [](void* memory)
174  {
175  T* dataPointer = static_cast<T*>(memory);
176  delete dataPointer;
177  };
178  auto cloner = [](void* memory)
179  {
180  T* dataPointer = static_cast<T*>(memory);
181  return new T{*dataPointer};
182  };
183  data[key] = UnsafeAny(new T{}, deleter, cloner);
184 #endif
185  }
186 
187  template<typename T>
193  const T& GetValue(const std::string& key) const
194  {
195  std::lock_guard<std::mutex> lock{mutex};
196  auto iterator = data.find(key);
197  if(iterator == data.end())
198  {
199  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, Severity::CRITICAL, "Invalid key (" + key + ")");
200  }
201 #ifndef BUILD_UNREAL
202  return std::any_cast<const T&>(iterator->second);
203 #else
204  return *static_cast<T*>(iterator->second.GetDataPointer());
205 #endif
206  }
207 
208  template<typename T>
214  T& GetOrAddValue(const std::string& key)
215  {
216  std::lock_guard<std::mutex> lock{ mutex };
217 #ifndef BUILD_UNREAL
218  return std::any_cast<T&>(data[key]);
219 #else
220  auto iterator = data.find(key);
221  if(iterator == data.end())
222  {
223  auto deleter = [](void* memory)
224  {
225  T* dataPointer = static_cast<T*>(memory);
226  delete dataPointer;
227  };
228  auto cloner = [](void* memory)
229  {
230  T* dataPointer = static_cast<T*>(memory);
231  return new T{*dataPointer};
232  };
233  iterator = data.emplace(std::piecewise_construct, std::forward_as_tuple(key),
234  std::forward_as_tuple(new T{}, deleter, cloner)).first;
235  }
236  return *static_cast<T*>(iterator->second.GetDataPointer());
237 #endif
238  }
239 
240  template<typename T>
247  bool TryGetValue(const std::string& key, T& outValue) const
248  {
249  std::lock_guard<std::mutex> lock{mutex};
250  auto iter = data.find(key);
251  if (iter != data.end())
252  {
253 #ifndef BUILD_UNREAL
254  outValue = std::any_cast<T>(iter->second);
255 #else
256  outValue = *static_cast<T*>(iter->second.GetDataPointer());
257 #endif
258  return true;
259  }
260  return false;
261  }
262 
263  void AddDataToNameMap(std::map<std::string, std::string>& outMap) const;
264 
265  private:
266 #ifndef BUILD_UNREAL
267  std::map<std::string, std::any> data{};
268 #else
269  class UnsafeAny
270  {
271  friend bool operator == (const UnsafeAny& first, const UnsafeAny& second);
272 
273  public:
274  UnsafeAny() = default;
275  UnsafeAny(void* dataPointer, std::function<void(void*)> deleter, std::function<void*(void*)> cloner);
276 
277  UnsafeAny(const UnsafeAny& other);
278  UnsafeAny(UnsafeAny&& other);
279 
280  ~UnsafeAny();
281 
282  UnsafeAny& operator = (const UnsafeAny& other);
283  UnsafeAny& operator = (UnsafeAny&& other);
284 
285  void* GetDataPointer() const;
286 
287  private:
288  void* dataPointer{nullptr};
289  std::function<void(void*)> deleter{[](void*){}};
290  std::function<void*(void*)> cloner{[](void*){ return nullptr; }};
291  };
292 
293  std::map<std::string, UnsafeAny> data{};
294 #endif
295  mutable std::mutex mutex{};
296  };
297 }
298 
299 #endif //GRAIL_BLACKBOARD_H
The Blackboard class - grail's universal data container.
Definition: Blackboard.hh:21
static const std::any & TheirsStrategy(const std::any &ours, const std::any &theirs)
TheirsStrategy.
Definition: Blackboard.cpp:52
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:142
bool ContainsKey(const std::string &key) const
ContainsKey - Checks whether this blackboard contains given key.
Definition: Blackboard.cpp:98
T & GetOrAddValue(const std::string &key)
GetOrAddValue - Returns value keyed with name. If blackboard does not contain key,...
Definition: Blackboard.hh:214
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:114
size_t Size() const
Size.
Definition: Blackboard.cpp:104
void SetDefaultValue(const std::string &key)
SetDefaultValue - Inserts default value of given type keyed with name into this blackboard....
Definition: Blackboard.hh:167
void RemoveEntry(const std::string &key)
RemoveValue - Deletes value keyed with given name from this blackboard.
Definition: Blackboard.cpp:92
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:193
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:247
static const std::any & OursStrategy(const std::any &ours, const std::any &theirs)
OursStrategy.
Definition: Blackboard.cpp:43
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:61
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:29