blackboard.h
Go to the documentation of this file.
1 #ifndef BLACKBOARD_H
2 #define BLACKBOARD_H
3 
4 #include <iostream>
5 #include <string>
6 #include <memory>
7 #include <stdint.h>
8 #include <unordered_map>
9 #include <mutex>
10 #include <sstream>
11 
15 
16 namespace BT
17 {
23 {
24 public:
25  typedef std::shared_ptr<Blackboard> Ptr;
26 
27 protected:
28  // This is intentionally protected. Use Blackboard::create instead
30  {}
31 
32 public:
37  {
38  return std::shared_ptr<Blackboard>(new Blackboard(parent));
39  }
40 
41  virtual ~Blackboard() = default;
42 
43  void enableAutoRemapping(bool remapping);
44 
51  const Any* getAny(const std::string& key) const
52  {
53  std::unique_lock<std::mutex> lock(mutex_);
54  auto it = storage_.find(key);
55 
56  if(it == storage_.end())
57  {
58  // Try with autoremapping. This should work recursively
59  if(autoremapping_)
60  {
61  if(auto parent = parent_bb_.lock()) {
62  return parent->getAny(key);
63  }
64  }
65  return nullptr;
66  }
67  return &(it->second->value);
68  }
69 
70  Any* getAny(const std::string& key)
71  {
72  // "Avoid Duplication in const and Non-const Member Function,"
73  // on p. 23, in Item 3 "Use const whenever possible," in Effective C++, 3d ed
74  return const_cast<Any*>(static_cast<const Blackboard&>(*this).getAny(key));
75  }
76 
80  template <typename T>
81  bool get(const std::string& key, T& value) const
82  {
83  const Any* val = getAny(key);
84  if (val)
85  {
86  value = val->cast<T>();
87  }
88  return (bool)val;
89  }
90 
94  template <typename T>
95  T get(const std::string& key) const
96  {
97  const Any* val = getAny(key);
98  if (val)
99  {
100  return val->cast<T>();
101  }
102  else
103  {
104  throw RuntimeError("Blackboard::get() error. Missing key [", key, "]");
105  }
106  }
107 
109  template <typename T>
110  void set(const std::string& key, const T& value)
111  {
112  std::unique_lock<std::mutex> lock_entry(entry_mutex_);
113  std::unique_lock<std::mutex> lock(mutex_);
114 
115  // check local storage
116  auto it = storage_.find(key);
117  std::shared_ptr<Entry> entry;
118  if (it != storage_.end())
119  {
120  entry = it->second;
121  }
122  else
123  {
124  Any new_value(value);
125  lock.unlock();
126  entry = createEntryImpl(key, PortInfo(PortDirection::INOUT, new_value.type(), {}));
127  entry->value = new_value;
128  return;
129  }
130 
131  const PortInfo& port_info = entry->port_info;
132  auto& previous_any = entry->value;
133  const auto previous_type = port_info.type();
134 
135  Any new_value(value);
136 
137  if (previous_type && *previous_type != typeid(T) &&
138  *previous_type != new_value.type())
139  {
140  bool mismatching = true;
141  if (std::is_constructible<StringView, T>::value)
142  {
143  Any any_from_string = port_info.parseString(value);
144  if (any_from_string.empty() == false)
145  {
146  mismatching = false;
147  new_value = std::move(any_from_string);
148  }
149  }
150 
151  if (mismatching)
152  {
153  debugMessage();
154 
155  throw LogicError("Blackboard::set() failed: once declared, the type of a port "
156  "shall not change. Declared type [",
157  BT::demangle(previous_type), "] != current type [",
158  BT::demangle(typeid(T)), "]");
159  }
160  }
161  previous_any = std::move(new_value);
162  }
163 
164  const PortInfo* portInfo(const std::string& key);
165 
166  void addSubtreeRemapping(StringView internal, StringView external);
167 
168  void debugMessage() const;
169 
170  std::vector<StringView> getKeys() const;
171 
172  void clear()
173  {
174  std::unique_lock<std::mutex> lock(mutex_);
175  storage_.clear();
176  internal_to_external_.clear();
177  }
178 
179  // Lock this mutex before using get() and getAny() and unlock it while you have
180  // done using the value.
182  {
183  return entry_mutex_;
184  }
185 
186  void createEntry(const std::string& key, const PortInfo& info)
187  {
188  createEntryImpl(key, info);
189  }
190 
191 private:
192  struct Entry
193  {
196 
197  Entry(const PortInfo& info) : port_info(info)
198  {}
199 
200  Entry(Any&& other_any, const PortInfo& info) :
201  value(std::move(other_any)), port_info(info)
202  {}
203  };
204 
205  std::shared_ptr<Entry> createEntryImpl(const std::string& key, const PortInfo& info);
206 
209  std::unordered_map<std::string, std::shared_ptr<Entry>> storage_;
210  std::weak_ptr<Blackboard> parent_bb_;
211  std::unordered_map<std::string, std::string> internal_to_external_;
212 
213  bool autoremapping_ = false;
214 };
215 
216 } // namespace BT
217 
218 #endif // BLACKBOARD_H
virtual ~Blackboard()=default
std::shared_ptr< Entry > createEntryImpl(const std::string &key, const PortInfo &info)
Definition: blackboard.cpp:68
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:36
const std::type_info & type() const noexcept
Definition: safe_any.hpp:143
const PortInfo * portInfo(const std::string &key)
Definition: blackboard.cpp:10
static pthread_mutex_t mutex
Definition: minitrace.cpp:61
Definition: any.hpp:455
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:25
Any * getAny(const std::string &key)
Definition: blackboard.h:70
const std::type_info * type() const
std::unordered_map< std::string, std::string > internal_to_external_
Definition: blackboard.h:211
The Blackboard is the mechanism used by BehaviorTrees to exchange typed data.
Definition: blackboard.h:22
T cast() const
Definition: safe_any.hpp:120
std::string demangle(char const *name)
Definition: demangle_util.h:72
bool autoremapping_
Definition: blackboard.h:213
bool empty() const noexcept
Definition: safe_any.hpp:153
std::mutex entry_mutex_
Definition: blackboard.h:208
nonstd::string_view StringView
Definition: basic_types.h:55
std::weak_ptr< Blackboard > parent_bb_
Definition: blackboard.h:210
Entry(Any &&other_any, const PortInfo &info)
Definition: blackboard.h:200
std::mutex mutex_
Definition: blackboard.h:207
const PortInfo port_info
Definition: blackboard.h:195
std::mutex & entryMutex()
Definition: blackboard.h:181
void createEntry(const std::string &key, const PortInfo &info)
Definition: blackboard.h:186
std::unordered_map< std::string, std::shared_ptr< Entry > > storage_
Definition: blackboard.h:209
Entry(const PortInfo &info)
Definition: blackboard.h:197
const Any * getAny(const std::string &key) const
The method getAny allow the user to access directly the type erased value.
Definition: blackboard.h:51
void debugMessage() const
Definition: blackboard.cpp:24
std::vector< StringView > getKeys() const
Definition: blackboard.cpp:52
Any parseString(const char *str) const
Blackboard(Blackboard::Ptr parent)
Definition: blackboard.h:29
void addSubtreeRemapping(StringView internal, StringView external)
Definition: blackboard.cpp:18
void enableAutoRemapping(bool remapping)
Definition: blackboard.cpp:5


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14