(C++)  1.1.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() = 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, 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
53 
54 
61 #ifndef BUILD_UNREAL
62  static const std::any& OursStrategy(const std::any& ours, const std::any& theirs);
63 #else
64  static const UnsafeAny& OursStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
65 #endif
66 
67 
74 #ifndef BUILD_UNREAL
75  static const std::any& TheirsStrategy(const std::any& ours, const std::any& theirs);
76 #else
77  static const UnsafeAny& TheirsStrategy(const UnsafeAny& ours, const UnsafeAny& theirs);
78 #endif
79 
85 #ifndef BUILD_UNREAL
86  void Merge(const Blackboard& other, std::function<const std::any&(const std::any&, const std::any&)> mergeStrategy = OursStrategy);
87 #else
88  void Merge(const Blackboard& other, std::function<const UnsafeAny&(const UnsafeAny&, const UnsafeAny&)> mergeStrategy = OursStrategy);
89 #endif
90 
91 
96  void RemoveEntry(const std::string& key);
97 
103  bool ContainsKey(const std::string& key) const;
104 
109  size_t Size() const;
110 
111  template<typename T>
117  void SetValue(const std::string& key, const T& value)
118  {
119  std::lock_guard<std::mutex> lock{mutex};
120 #ifndef BUILD_UNREAL
121  std::any any = value;
122  data[key] = any;
123 #else
124  auto deleter = [](void* memory)
125  {
126  T* dataPointer = static_cast<T*>(memory);
127  delete dataPointer;
128  };
129  auto cloner = [](void* memory)
130  {
131  T* dataPointer = static_cast<T*>(memory);
132  return new T{*dataPointer};
133  };
134 
135  data[key] = UnsafeAny(new T{value}, deleter, cloner);
136 #endif
137  }
138 
139  template<typename T, std::enable_if_t<!std::is_reference<T>::value>* = nullptr>
145  void SetValue(const std::string& key, T&& value)
146  {
147  std::lock_guard<std::mutex> lock{mutex};
148 #ifndef BUILD_UNREAL
149  data[key] = std::any{value};
150 #else
151  auto deleter = [](void* memory)
152  {
153  T* dataPointer = static_cast<T*>(memory);
154  delete dataPointer;
155  };
156  auto cloner = [](void* memory)
157  {
158  T* dataPointer = static_cast<T*>(memory);
159  return new T{*dataPointer};
160  };
161  data[key] = UnsafeAny(new T{value}, deleter, cloner);
162 #endif
163  }
164 
165  template<typename T>
170  void SetDefaultValue(const std::string& key)
171  {
172  std::lock_guard<std::mutex> lock{mutex};
173 #ifndef BUILD_UNREAL
174  data[key] = std::any{T{}};
175 #else
176  auto deleter = [](void* memory)
177  {
178  T* dataPointer = static_cast<T*>(memory);
179  delete dataPointer;
180  };
181  auto cloner = [](void* memory)
182  {
183  T* dataPointer = static_cast<T*>(memory);
184  return new T{*dataPointer};
185  };
186  data[key] = UnsafeAny(new T{}, deleter, cloner);
187 #endif
188  }
189 
190  template<typename T>
196  const T& GetValue(const std::string& key) const
197  {
198  std::lock_guard<std::mutex> lock{mutex};
199  auto iterator = data.find(key);
200  if(iterator == data.end())
201  {
202  GRAIL_LOG(consts::DEFAULT_GRAIL_LOG_GROUP, Severity::CRITICAL, "Invalid key (" + key + ")");
203  }
204 #ifndef BUILD_UNREAL
205  return std::any_cast<const T&>(iterator->second);
206 #else
207  return *static_cast<T*>(iterator->second.GetDataPointer());
208 #endif
209  }
210 
211  template<typename T>
217  T& GetOrAddValue(const std::string& key)
218  {
219  std::lock_guard<std::mutex> lock{ mutex };
220 #ifndef BUILD_UNREAL
221  return std::any_cast<T&>(data[key]);
222 #else
223  auto iterator = data.find(key);
224  if(iterator == data.end())
225  {
226  auto deleter = [](void* memory)
227  {
228  T* dataPointer = static_cast<T*>(memory);
229  delete dataPointer;
230  };
231  auto cloner = [](void* memory)
232  {
233  T* dataPointer = static_cast<T*>(memory);
234  return new T{*dataPointer};
235  };
236  iterator = data.emplace(std::piecewise_construct, std::forward_as_tuple(key),
237  std::forward_as_tuple(new T{}, deleter, cloner)).first;
238  }
239  return *static_cast<T*>(iterator->second.GetDataPointer());
240 #endif
241  }
242 
243  template<typename T>
250  bool TryGetValue(const std::string& key, T& outValue) const
251  {
252  std::lock_guard<std::mutex> lock{mutex};
253  auto iter = data.find(key);
254  if (iter != data.end())
255  {
256 #ifndef BUILD_UNREAL
257  outValue = std::any_cast<T>(iter->second);
258 #else
259  outValue = *static_cast<T*>(iter->second.GetDataPointer());
260 #endif
261  return true;
262  }
263  return false;
264  }
265 
266  void AddDataToNameMap(std::map<std::string, std::string>& outMap) const;
267 
268  private:
269 #ifndef BUILD_UNREAL
270  std::map<std::string, std::any> data{};
271 #else
272  class UnsafeAny
273  {
274  friend bool operator == (const UnsafeAny& first, const UnsafeAny& second);
275 
276  public:
277  UnsafeAny() = default;
278  UnsafeAny(void* dataPointer, std::function<void(void*)> deleter, std::function<void*(void*)> cloner);
279 
280  UnsafeAny(const UnsafeAny& other);
281  UnsafeAny(UnsafeAny&& other);
282 
283  ~UnsafeAny();
284 
285  UnsafeAny& operator = (const UnsafeAny& other);
286  UnsafeAny& operator = (UnsafeAny&& other);
287 
288  void* GetDataPointer() const;
289 
290  private:
291  void* dataPointer{nullptr};
292  std::function<void(void*)> deleter{[](void*){}};
293  std::function<void*(void*)> cloner{[](void*){ return nullptr; }};
294  };
295 
296  std::map<std::string, UnsafeAny> data{};
297 #endif
298  mutable std::mutex mutex{};
299  };
300 }
301 
302 #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:46
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:145
bool ContainsKey(const std::string &key) const
ContainsKey - Checks whether this blackboard contains given key.
Definition: Blackboard.cpp:92
T & GetOrAddValue(const std::string &key)
GetOrAddValue - Returns value keyed with name. If blackboard does not contain key,...
Definition: Blackboard.hh:217
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:117
size_t Size() const
Size.
Definition: Blackboard.cpp:98
void SetDefaultValue(const std::string &key)
SetDefaultValue - Inserts default value of given type keyed with name into this blackboard....
Definition: Blackboard.hh:170
void RemoveEntry(const std::string &key)
RemoveValue - Deletes value keyed with given name from this blackboard.
Definition: Blackboard.cpp:86
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:196
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:250
static const std::any & OursStrategy(const std::any &ours, const std::any &theirs)
OursStrategy.
Definition: Blackboard.cpp:37
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:55
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:23