1515
1616#include " behaviortree_cpp/action_node.h"
1717
18+ #include < mutex>
19+
1820namespace BT
1921{
2022/* *
@@ -76,13 +78,18 @@ class SetBlackboardNode : public SyncActionNode
7678 {
7779 throw RuntimeError (" Can't find the port referred by [value]" );
7880 }
81+ // Entry::value and Entry::info are shared with any thread that writes
82+ // the same entry (Blackboard::set holds entry_mutex while reassigning
83+ // them), so they must be copied under the same mutex.
84+ std::unique_lock src_lock (src_entry->entry_mutex );
85+ out_value = src_entry->value ;
86+ const TypeInfo src_info = src_entry->info ;
87+ src_lock.unlock ();
7988 if (!dst_entry)
8089 {
81- config ().blackboard ->createEntry (output_key, src_entry-> info );
90+ config ().blackboard ->createEntry (output_key, src_info );
8291 dst_entry = config ().blackboard ->getEntry (output_key);
8392 }
84-
85- out_value = src_entry->value ;
8693 }
8794 else
8895 {
@@ -94,17 +101,24 @@ class SetBlackboardNode : public SyncActionNode
94101
95102 // avoid type issues when port is remapped: current implementation of the set might be a little bit problematic for initialized on the fly values
96103 // this still does not attack math issues
97- if (dst_entry && dst_entry-> info . type () != typeid (std::string) && out_value.isString ())
104+ if (dst_entry && out_value.isString ())
98105 {
99- try
100- {
101- out_value = dst_entry->info .parseString (out_value.cast <std::string>());
102- }
103- catch (const std::exception& e)
106+ // same as above: Entry::info may be reassigned under entry_mutex by a
107+ // concurrent Blackboard::set, so take a copy under the same mutex.
108+ std::unique_lock dst_lock (dst_entry->entry_mutex );
109+ const TypeInfo dst_info = dst_entry->info ;
110+ dst_lock.unlock ();
111+ if (dst_info.type () != typeid (std::string))
104112 {
105- throw LogicError (" Can't convert string [" , out_value.cast <std::string>(),
106- " ] to type [" , BT::demangle (dst_entry->info .type ()),
107- " ]: " , e.what ());
113+ try
114+ {
115+ out_value = dst_info.parseString (out_value.cast <std::string>());
116+ }
117+ catch (const std::exception& e)
118+ {
119+ throw LogicError (" Can't convert string [" , out_value.cast <std::string>(),
120+ " ] to type [" , BT::demangle (dst_info.type ()), " ]: " , e.what ());
121+ }
108122 }
109123 }
110124
0 commit comments