diff --git a/yasmin/include/yasmin/blackboard/blackboard.hpp b/yasmin/include/yasmin/blackboard/blackboard.hpp index 68487de..8e3c6c8 100644 --- a/yasmin/include/yasmin/blackboard/blackboard.hpp +++ b/yasmin/include/yasmin/blackboard/blackboard.hpp @@ -17,6 +17,7 @@ #define YASMIN_BLACKBOARD_HPP #include +#include #include #include "yasmin/blackboard/blackboard_value.hpp" @@ -28,6 +29,7 @@ namespace blackboard { class Blackboard { private: + std::recursive_mutex mutex; std::map values; public: @@ -35,17 +37,10 @@ class Blackboard { Blackboard(const Blackboard &other); ~Blackboard(); - template void set(std::string name, T value) { - if (!this->contains(name)) { - BlackboardValue *b_value = new BlackboardValue(value); - this->values.insert({name, b_value}); + template T get(std::string name) { - } else { - ((BlackboardValue *)this->values.at(name))->set(value); - } - } + std::lock_guard lk(this->mutex); - template T get(std::string name) { if (!this->contains(name)) { throw "Element " + name + " does not exist in the blackboard"; } @@ -54,8 +49,22 @@ class Blackboard { return b_value->get(); } - bool contains(std::string name); + template void set(std::string name, T value) { + std::lock_guard lk(this->mutex); + + if (!this->contains(name)) { + BlackboardValue *b_value = new BlackboardValue(value); + this->values.insert({name, b_value}); + + } else { + ((BlackboardValue *)this->values.at(name))->set(value); + } + } + + void remove(std::string name); + bool contains(std::string name); + int size(); std::string to_string(); }; diff --git a/yasmin/src/yasmin/blackboard/blackboard.cpp b/yasmin/src/yasmin/blackboard/blackboard.cpp index 0c96af2..5f1a894 100644 --- a/yasmin/src/yasmin/blackboard/blackboard.cpp +++ b/yasmin/src/yasmin/blackboard/blackboard.cpp @@ -34,12 +34,26 @@ Blackboard::~Blackboard() { } } +void Blackboard::remove(std::string name) { + std::lock_guard lk(this->mutex); + delete this->values.at(name); + this->values.erase(name); +} + bool Blackboard::contains(std::string name) { + std::lock_guard lk(this->mutex); return (this->values.find(name) != this->values.end()); } +int Blackboard::size() { + std::lock_guard lk(this->mutex); + return this->values.size(); +} + std::string Blackboard::to_string() { + std::lock_guard lk(this->mutex); + std::string result = "Blackboard\n"; for (const auto &ele : this->values) { diff --git a/yasmin/tests/python/test_blackboard.py b/yasmin/tests/python/test_blackboard.py index f99cacb..028f139 100644 --- a/yasmin/tests/python/test_blackboard.py +++ b/yasmin/tests/python/test_blackboard.py @@ -21,22 +21,21 @@ class TestBlackboard(unittest.TestCase): def setUp(self): - self.blackboard = Blackboard() def test_blackboard_get(self): - self.blackboard.__setitem__("foo", "foo") - self.assertEqual("foo", self.blackboard.__getitem__("foo")) + self.blackboard["foo"] = "foo" + self.assertEqual("foo", self.blackboard["foo"]) def test_blackboard_delete(self): - self.blackboard.__setitem__("foo", "foo") - self.blackboard.__delitem__("foo") - self.assertFalse(self.blackboard.__contains__("foo")) + self.blackboard["foo"] = "foo" + del self.blackboard["foo"] + self.assertFalse("foo" in self.blackboard) def test_blackboard_contains(self): - self.blackboard.__setitem__("foo", "foo") - self.assertTrue(self.blackboard.__contains__("foo")) + self.blackboard["foo"] = "foo" + self.assertTrue("foo" in self.blackboard) def test_blackboard_len(self): - self.blackboard.__setitem__("foo", "foo") - self.assertEqual(1, self.blackboard.__len__()) + self.blackboard["foo"] = "foo" + self.assertEqual(1, len(self.blackboard)) diff --git a/yasmin/yasmin/blackboard.py b/yasmin/yasmin/blackboard.py index b58743b..63d9caa 100644 --- a/yasmin/yasmin/blackboard.py +++ b/yasmin/yasmin/blackboard.py @@ -14,28 +14,38 @@ # along with this program. If not, see . -from typing import Any +from typing import Any, Dict +from threading import Lock class Blackboard(object): - def __init__(self, init=None) -> None: + + def __init__(self, init: Dict[str, Any] = None) -> None: + self.__lock = Lock() + self._data = {} if init is not None: - self.__dict__.update(init) + self._data.update(init) def __getitem__(self, key) -> Any: - return self.__dict__[key] + with self.__lock: + return self._data[key] def __setitem__(self, key, value) -> None: - self.__dict__[key] = value + with self.__lock: + self._data[key] = value def __delitem__(self, key) -> None: - del self.__dict__[key] + with self.__lock: + del self._data[key] def __contains__(self, key) -> bool: - return key in self.__dict__ + with self.__lock: + return key in self._data def __len__(self) -> int: - return len(self.__dict__) + with self.__lock: + return len(self._data) def __repr__(self) -> str: - return repr(self.__dict__) + with self.__lock: + return repr(self._data) diff --git a/yasmin_ros/tests/python/test_yasmin_ros.py b/yasmin_ros/tests/python/test_yasmin_ros.py index e324772..91e43ab 100644 --- a/yasmin_ros/tests/python/test_yasmin_ros.py +++ b/yasmin_ros/tests/python/test_yasmin_ros.py @@ -19,7 +19,7 @@ from threading import Thread from yasmin_ros import ActionState, ServiceState, MonitorState -from yasmin_ros.basic_outcomes import SUCCEED, CANCEL, ABORT +from yasmin_ros.basic_outcomes import SUCCEED, CANCEL, ABORT, TIMEOUT from example_interfaces.action import Fibonacci from example_interfaces.srv import AddTwoInts @@ -195,4 +195,4 @@ def monitor_handler(blackboard, msg): state = MonitorState(String, "test1", [SUCCEED], monitor_handler=monitor_handler, timeout=2) - self.assertEqual(CANCEL, state()) + self.assertEqual(TIMEOUT, state())