Skip to content

Commit 224358b

Browse files
committed
deprecating getAny
1 parent fd7a0ab commit 224358b

File tree

8 files changed

+277
-97
lines changed

8 files changed

+277
-97
lines changed

include/behaviortree_cpp/blackboard.h

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,27 @@
66
#include <stdint.h>
77
#include <unordered_map>
88
#include <mutex>
9+
#include <shared_mutex>
910
#include <sstream>
1011

1112
#include "behaviortree_cpp/basic_types.h"
1213
#include "behaviortree_cpp/utils/safe_any.hpp"
1314
#include "behaviortree_cpp/exceptions.h"
15+
#include "behaviortree_cpp/utils/locked_reference.hpp"
1416

1517
namespace BT
1618
{
19+
20+
using AnyReadRef = LockedConstRef<Any>;
21+
using AnyWriteRef = LockedRef<Any>;
22+
1723
/**
1824
* @brief The Blackboard is the mechanism used by BehaviorTrees to exchange
1925
* typed data.
2026
*/
2127
class Blackboard
2228
{
29+
2330
public:
2431
typedef std::shared_ptr<Blackboard> Ptr;
2532

@@ -29,6 +36,21 @@ class Blackboard
2936
{}
3037

3138
public:
39+
40+
struct Entry
41+
{
42+
Any value;
43+
PortInfo port_info;
44+
std::shared_mutex entry_mutex;
45+
46+
Entry(const PortInfo& info) : port_info(info)
47+
{}
48+
49+
Entry(Any&& other_any, const PortInfo& info) :
50+
value(std::move(other_any)), port_info(info)
51+
{}
52+
};
53+
3254
/** Use this static method to create an instance of the BlackBoard
3355
* to share among all your NodeTrees.
3456
*/
@@ -39,13 +61,7 @@ class Blackboard
3961

4062
virtual ~Blackboard() = default;
4163

42-
/**
43-
* @brief The method getAny allow the user to access directly the type
44-
* erased value.
45-
*
46-
* @return the pointer or nullptr if it fails.
47-
*/
48-
const Any* getAny(const std::string& key) const
64+
const Entry* getEntry(const std::string& key) const
4965
{
5066
std::unique_lock<std::mutex> lock(mutex_);
5167
// search first if this port was remapped
@@ -56,19 +72,49 @@ class Blackboard
5672
auto remapping_it = internal_to_external_.find(key);
5773
if (remapping_it != internal_to_external_.end())
5874
{
59-
return parent->getAny(remapping_it->second);
75+
return parent->getEntry(remapping_it->second);
6076
}
6177
}
6278
}
6379
auto it = storage_.find(key);
64-
return (it == storage_.end()) ? nullptr : &(it->second.value);
80+
return (it == storage_.end()) ? nullptr : it->second.get();
6581
}
6682

67-
Any* getAny(const std::string& key)
83+
Entry* getEntry(const std::string& key)
6884
{
6985
// "Avoid Duplication in const and Non-const Member Function,"
7086
// on p. 23, in Item 3 "Use const whenever possible," in Effective C++, 3d ed
71-
return const_cast<Any*>( static_cast<const Blackboard &>(*this).getAny(key));
87+
return const_cast<Entry*>( static_cast<const Blackboard &>(*this).getEntry(key));
88+
}
89+
90+
AnyReadRef getAnyRead(const std::string& key) const
91+
{
92+
if(auto entry = getEntry(key))
93+
{
94+
return AnyReadRef(&entry->value, const_cast<std::shared_mutex*>(&entry->entry_mutex));
95+
}
96+
return {};
97+
}
98+
99+
AnyWriteRef getAnyWrite(const std::string& key)
100+
{
101+
if(auto entry = getEntry(key))
102+
{
103+
return AnyWriteRef(&entry->value, &entry->entry_mutex);
104+
}
105+
return {};
106+
}
107+
108+
[[deprecated("Use getAnyRead instead")]]
109+
const Any* getAny(const std::string& key) const
110+
{
111+
return getAnyRead(key).get();
112+
}
113+
114+
[[deprecated("Use getAnyWrite instead")]]
115+
Any* getAny(const std::string& key)
116+
{
117+
return getAnyWrite(key).get();
72118
}
73119

74120
/** Return true if the entry with the given key was found.
@@ -77,12 +123,12 @@ class Blackboard
77123
template <typename T>
78124
bool get(const std::string& key, T& value) const
79125
{
80-
const Any* val = getAny(key);
81-
if (val)
126+
if (auto any_ref = getAnyRead(key))
82127
{
83-
value = val->cast<T>();
128+
value = any_ref.get()->cast<T>();
129+
return true;
84130
}
85-
return (bool)val;
131+
return false;
86132
}
87133

88134
/**
@@ -91,10 +137,9 @@ class Blackboard
91137
template <typename T>
92138
T get(const std::string& key) const
93139
{
94-
const Any* val = getAny(key);
95-
if (val)
140+
if (auto any_ref = getAnyRead(key))
96141
{
97-
return val->cast<T>();
142+
return any_ref.get()->cast<T>();
98143
}
99144
else
100145
{
@@ -106,7 +151,6 @@ class Blackboard
106151
template <typename T>
107152
void set(const std::string& key, const T& value)
108153
{
109-
std::unique_lock lock_entry(entry_mutex_);
110154
std::unique_lock lock(mutex_);
111155

112156
// search first if this port was remapped.
@@ -133,19 +177,21 @@ class Blackboard
133177
if (std::is_constructible<StringView, T>::value)
134178
{
135179
PortInfo new_port(PortDirection::INOUT, typeid(std::string), {});
136-
storage_.emplace(key, Entry(Any(value), new_port));
180+
storage_.emplace(key, std::make_unique<Entry>(Any(value), new_port));
137181
}
138182
else
139183
{
140184
PortInfo new_port(PortDirection::INOUT, typeid(T), {});
141-
storage_.emplace(key, Entry(Any(value), new_port));
185+
storage_.emplace(key, std::make_unique<Entry>(Any(value), new_port));
142186
}
143187
}
144188
else
145189
{
146190
// this is not the first time we set this entry, we need to check
147191
// if the type is the same or not.
148-
Entry& entry = it->second;
192+
Entry& entry = *it->second;
193+
std::scoped_lock lock(entry.entry_mutex);
194+
149195
Any& previous_any = entry.value;
150196
const PortInfo& port_info = entry.port_info;
151197

@@ -209,30 +255,9 @@ class Blackboard
209255
storage_.clear();
210256
}
211257

212-
// Lock this mutex before using get() and getAny() and unlock it while you have
213-
// done using the value.
214-
std::recursive_mutex& entryMutex() const
215-
{
216-
return entry_mutex_;
217-
}
218-
219258
private:
220-
struct Entry
221-
{
222-
Any value;
223-
PortInfo port_info;
224-
225-
Entry(const PortInfo& info) : port_info(info)
226-
{}
227-
228-
Entry(Any&& other_any, const PortInfo& info) :
229-
value(std::move(other_any)), port_info(info)
230-
{}
231-
};
232-
233259
mutable std::mutex mutex_;
234-
mutable std::recursive_mutex entry_mutex_;
235-
std::unordered_map<std::string, Entry> storage_;
260+
std::unordered_map<std::string, std::unique_ptr<Entry>> storage_;
236261
std::weak_ptr<Blackboard> parent_bb_;
237262
std::unordered_map<std::string, std::string> internal_to_external_;
238263

include/behaviortree_cpp/scripting/operators.hpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,12 @@ struct ExprName : ExprBase
6868
}
6969
}
7070
// search now in the variables table
71-
std::unique_lock entry_lock(env.vars->entryMutex());
72-
auto any_ptr = env.vars->getAny(name);
73-
if( !any_ptr )
71+
auto any_ref = env.vars->getAnyRead(name);
72+
if( !any_ref )
7473
{
75-
throw std::runtime_error("Variable not found");
74+
throw std::runtime_error("Variable not found");
7675
}
77-
return *any_ptr;
76+
return *any_ref.get();
7877
}
7978
};
8079

@@ -360,15 +359,14 @@ struct ExprAssignment : ExprBase
360359
}
361360
const auto& key = varname->name;
362361

363-
std::unique_lock entry_lock(env.vars->entryMutex());
364-
Any* any_ptr = env.vars->getAny(key);
365-
if( !any_ptr )
362+
Blackboard::Entry* entry = env.vars->getEntry(key);
363+
if( !entry )
366364
{
367365
// variable doesn't exist, create it if using operator assign_create
368366
if(op == assign_create)
369367
{
370368
env.vars->setPortInfo(key, PortInfo());
371-
any_ptr = env.vars->getAny(key);
369+
entry = env.vars->getEntry(key);
372370
}
373371
else {
374372
// fail otherwise
@@ -377,6 +375,9 @@ struct ExprAssignment : ExprBase
377375
}
378376
auto value = rhs->evaluate(env);
379377

378+
std::scoped_lock lock(entry->entry_mutex);
379+
auto any_ptr = &entry->value;
380+
380381
if( op == assign_create || op == assign_existing )
381382
{
382383
// special case first: string to other type

0 commit comments

Comments
 (0)