diff --git a/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp b/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp index 6664288a0fa5f86da4df906819cba3be385cbcb9..6826523b35ebab7e3fbe6c7708b22cc076ce7f61 100644 --- a/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp +++ b/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp @@ -111,8 +111,10 @@ namespace armarx::armem::server MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const armem::server::wm::CoreSegment& coreSegment) const { - std::scoped_lock lock(coreSegment.mutex()); - return this->_makeGroupBox(coreSegment); + return coreSegment.doLocked([this, &coreSegment]() + { + return this->_makeGroupBox(coreSegment); + }); } diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp index 52fb496592390a1f7df893d0709c73937da55ae5..a61fbfefa85c3371187dde11fbaca82fcacc6b3a 100644 --- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp +++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp @@ -60,20 +60,22 @@ namespace armarx::armem::server if (input.providerSegmentName.size() > 0) { - std::scoped_lock lock(coreSegment->mutex()); - try - { - coreSegment->addProviderSegment(input.providerSegmentName); - } - catch (const armem::error::ContainerEntryAlreadyExists&) + coreSegment->doLocked([&coreSegment, &input]() { - // This is ok. - if (input.clearWhenExists) + try { - server::wm::ProviderSegment& provider = coreSegment->getProviderSegment(input.providerSegmentName); - provider.clear(); + coreSegment->addProviderSegment(input.providerSegmentName); } - } + catch (const armem::error::ContainerEntryAlreadyExists&) + { + // This is ok. + if (input.clearWhenExists) + { + server::wm::ProviderSegment& provider = coreSegment->getProviderSegment(input.providerSegmentName); + provider.clear(); + } + } + }); } armem::MemoryID segmentID; diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp index 4e968623d63aa57213507879608c81823d31c7d6..0ace705be878087b9023ea574f50769489514cb5 100644 --- a/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp +++ b/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp @@ -55,8 +55,10 @@ namespace armarx::armem::server::query_proc::wm_server const armem::query::data::CoreSegmentQuery& query, const CoreSegment& coreSegment) const { - std::scoped_lock lock(coreSegment.mutex()); - CoreSegmentQueryProcessorBase::process(result, query, coreSegment); + coreSegment.doLocked([&]() + { + CoreSegmentQueryProcessorBase::process(result, query, coreSegment); + }); } diff --git a/source/RobotAPI/libraries/armem/server/segment/Segment.cpp b/source/RobotAPI/libraries/armem/server/segment/Segment.cpp index 050e77d392da77bc5c4e4edfcf11f76ee6e1e051..d538568c2430c9ffbd00c9b48bebcd46086280ea 100644 --- a/source/RobotAPI/libraries/armem/server/segment/Segment.cpp +++ b/source/RobotAPI/libraries/armem/server/segment/Segment.cpp @@ -48,14 +48,6 @@ namespace armarx::armem::server::segment } - std::mutex& wm::CoreSegmentBase::mutex() const - { - ARMARX_CHECK_NOT_NULL(segment); - return segment->mutex(); - } - - - wm::ProviderSegmentBase::ProviderSegmentBase( armem::server::MemoryToIceAdapter& iceMemory, const std::string& defaultProviderSegmentName, diff --git a/source/RobotAPI/libraries/armem/server/segment/Segment.h b/source/RobotAPI/libraries/armem/server/segment/Segment.h index 7808e99d31f4df3543bfbd5b882a408dda143ed5..a34f89e9cab53b75860599c1d6f5174400843abd 100644 --- a/source/RobotAPI/libraries/armem/server/segment/Segment.h +++ b/source/RobotAPI/libraries/armem/server/segment/Segment.h @@ -1,29 +1,16 @@ #pragma once -// STD/STL -#include <mutex> -#include <string> +#include <RobotAPI/libraries/armem/server/forward_declarations.h> +#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h> + +#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h> -// ArmarX #include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/application/properties/forward_declarations.h> -#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h> +#include <string> -namespace armarx::armem -{ - namespace server - { - class MemoryToIceAdapter; - - namespace wm - { - class CoreSegment; - class ProviderSegment; - } - } -} namespace armarx::armem::server::segment { namespace detail @@ -88,7 +75,11 @@ namespace armarx::armem::server::segment // virtual void onConnect() override; - std::mutex& mutex() const; + template <class FunctionT> + auto doLocked(FunctionT&& function) + { + return segment->doLocked(function); + } protected: diff --git a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp index 8184e27c985877a19aaa873db07883685140b17b..50f5ae6451bb49f9a4356579d78618a865297881 100644 --- a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp +++ b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp @@ -12,11 +12,11 @@ namespace armarx::armem::server::segment { SpecializedSegment::SpecializedSegment( - server::MemoryToIceAdapter& iceMemory, - aron::typenavigator::ObjectNavigatorPtr aronType, - const std::string& defaultCoreSegmentName, - int64_t defaultMaxHistorySize - ) : + server::MemoryToIceAdapter& iceMemory, + aron::typenavigator::ObjectNavigatorPtr aronType, + const std::string& defaultCoreSegmentName, + int64_t defaultMaxHistorySize + ) : iceMemory(iceMemory), aronType(aronType) { setDefaultCoreSegmentName(defaultCoreSegmentName); @@ -52,13 +52,6 @@ namespace armarx::armem::server::segment } - std::mutex& SpecializedSegment::mutex() const - { - ARMARX_CHECK_NOT_NULL(coreSegment); - return coreSegment->mutex(); - } - - void SpecializedSegment::setDefaultCoreSegmentName(const std::string& coreSegmentName) { this->properties.coreSegmentName = coreSegmentName; diff --git a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h index 460fbf3f0f0cd4ea6c2835d499071f2e43bf2a7d..59b198ec20be181a6359eee06e2ddac93be4cc1d 100644 --- a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h +++ b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h @@ -1,26 +1,14 @@ #pragma once -#include <mutex> -#include <string> +#include <RobotAPI/libraries/armem/server/forward_declarations.h> +#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h> +#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h> #include <ArmarXCore/core/application/properties/forward_declarations.h> #include <ArmarXCore/core/logging/Logging.h> -#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h> - - -namespace armarx::armem -{ - namespace server - { - class MemoryToIceAdapter; +#include <string> - namespace wm - { - class CoreSegment; - } - } -} namespace armarx::armem::server::segment { @@ -46,7 +34,12 @@ namespace armarx::armem::server::segment virtual void init(); // void connect(); - std::mutex& mutex() const; + + template <class FunctionT> + auto doLocked(FunctionT&& function) + { + return coreSegment->doLocked(function); + } protected: diff --git a/source/RobotAPI/libraries/armem/server/wm/memory_definitions.cpp b/source/RobotAPI/libraries/armem/server/wm/memory_definitions.cpp index 7cf7d4e225f9cdd0d360f6d372e0d5d21cf01f30..6f031a4d62811d871a5cd627081ad3741cfd3d4b 100644 --- a/source/RobotAPI/libraries/armem/server/wm/memory_definitions.cpp +++ b/source/RobotAPI/libraries/armem/server/wm/memory_definitions.cpp @@ -43,36 +43,6 @@ namespace armarx::armem::server::wm } - - std::mutex& CoreSegment::mutex() const - { - return _mutex; - } - - - - std::optional<wm::EntitySnapshot> - CoreSegment::getLatestEntitySnapshotLocking(const MemoryID& entityID) const - { - std::scoped_lock lock(_mutex); - return getLatestEntitySnapshot(entityID); - } - - std::optional<wm::EntityInstance> - CoreSegment::getLatestEntityInstanceLocking(const MemoryID& entityID, int instanceIndex) const - { - std::scoped_lock lock(_mutex); - return getLatestEntityInstance(entityID, instanceIndex); - } - - armarx::aron::datanavigator::DictNavigatorPtr - CoreSegment::getLatestEntityInstanceDataLocking(const MemoryID& entityID, int instanceIndex) const - { - std::scoped_lock lock(_mutex); - return getLatestEntityInstanceData(entityID, instanceIndex); - } - - // TODO: add core segment if param is set std::vector<Memory::Base::UpdateResult> Memory::updateLocking(const Commit& commit) @@ -95,15 +65,16 @@ namespace armarx::armem::server::wm CoreSegment& coreSegment = it->second; // Lock the core segment for the whole batch. - std::scoped_lock lock(coreSegment.mutex()); - - for (const EntityUpdate* update : updates) + coreSegment.doLocked([&result, &coreSegment, updates = &updates]() { - auto r = coreSegment.update(*update); - Base::UpdateResult ret { r }; - ret.memoryUpdateType = UpdateType::UpdatedExisting; - result.push_back(ret); - } + for (const EntityUpdate* update : *updates) + { + auto r = coreSegment.update(*update); + Base::UpdateResult ret { r }; + ret.memoryUpdateType = UpdateType::UpdatedExisting; + result.push_back(ret); + } + }); } else { @@ -129,10 +100,10 @@ namespace armarx::armem::server::wm CoreSegment& segment = getCoreSegment(update.entityID.coreSegmentName); Base::UpdateResult result; + segment.doLocked([&result, &segment, &update]() { - std::scoped_lock lock(segment.mutex()); result = segment.update(update); - } + }); result.memoryUpdateType = UpdateType::UpdatedExisting; return result; } diff --git a/source/RobotAPI/libraries/armem/server/wm/memory_definitions.h b/source/RobotAPI/libraries/armem/server/wm/memory_definitions.h index 0849a9b582e44b7f7c1e20942232a323fa1b4012..cb4aa1a0cc5c00783de70a77986998f07c08902c 100644 --- a/source/RobotAPI/libraries/armem/server/wm/memory_definitions.h +++ b/source/RobotAPI/libraries/armem/server/wm/memory_definitions.h @@ -10,6 +10,8 @@ #include <RobotAPI/libraries/armem/core/base/CoreSegmentBase.h> #include <RobotAPI/libraries/armem/core/base/MemoryBase.h> +#include <RobotAPI/libraries/armem/core/wm/detail/data_lookup_mixins.h> + #include <mutex> #include <optional> @@ -28,6 +30,7 @@ namespace armarx::armem::server::wm class Entity : public base::EntityBase<EntitySnapshot, Entity> , public detail::MaxHistorySize + , public armem::wm::detail::FindInstanceDataMixin<Entity> { public: @@ -55,8 +58,9 @@ namespace armarx::armem::server::wm /// @see base::ProviderSegmentBase class ProviderSegment : - public base::ProviderSegmentBase<Entity, ProviderSegment>, - public detail::MaxHistorySizeParent<ProviderSegment> + public base::ProviderSegmentBase<Entity, ProviderSegment> + , public detail::MaxHistorySizeParent<ProviderSegment> + , public armem::wm::detail::FindInstanceDataMixin<ProviderSegment> { public: @@ -81,6 +85,7 @@ namespace armarx::armem::server::wm class CoreSegment : public base::CoreSegmentBase<ProviderSegment, CoreSegment>, public detail::MaxHistorySizeParent<CoreSegment> + , public armem::wm::detail::FindInstanceDataMixin<CoreSegment> { using Base = base::CoreSegmentBase<ProviderSegment, CoreSegment>; @@ -88,38 +93,6 @@ namespace armarx::armem::server::wm using Base::CoreSegmentBase; - // ToDo: Replace by runLocked() - std::mutex& mutex() const; - - - // Non-locking interface - - std::optional<wm::EntitySnapshot> getLatestEntitySnapshot( - const MemoryID& entityID) const; - std::optional<wm::EntityInstance> getLatestEntityInstance( - const MemoryID& entityID, int instanceIndex = 0) const; - armarx::aron::datanavigator::DictNavigatorPtr getLatestEntityInstanceData( - const MemoryID& entityID, int instanceIndex = 0) const; - - - template <class AronDtoT> - std::optional<AronDtoT> getLatestEntityInstanceDataAs( - const MemoryID& entityID, int instanceIndex = 0) const - { - wm::EntityInstanceDataPtr data = getLatestEntityInstanceData(entityID, instanceIndex); - if (data) - { - AronDtoT aron; - aron.fromAron(data); - return aron; - } - else - { - return std::nullopt; - } - } - - /// @see base::CoreSegmentBase::addProviderSegment() using CoreSegmentBase::addProviderSegment; template <class ...Args> @@ -133,38 +106,15 @@ namespace armarx::armem::server::wm // Locking interface - std::optional<wm::EntitySnapshot> getLatestEntitySnapshotLocking( - const MemoryID& entityID) const; - std::optional<wm::EntityInstance> getLatestEntityInstanceLocking( - const MemoryID& entityID, int instanceIndex = 0) const; - armarx::aron::datanavigator::DictNavigatorPtr getLatestEntityInstanceDataLocking( - const MemoryID& entityID, int instanceIndex = 0) const; - - - template <class AronDtoT> - std::optional<AronDtoT> getLatestEntityInstanceDataLockingAs( - const MemoryID& entityID, int instanceIndex = 0) const + template <class FunctionT> + auto doLocked(FunctionT&& function) const { - // Keep lock to a minimum. - wm::EntityInstanceDataPtr data = nullptr; - { - std::scoped_lock lock(_mutex); - data = getLatestEntityInstanceData(entityID, instanceIndex); - } - if (data) - { - AronDtoT aron; - aron.fromAron(data); - return aron; - } - else - { - return std::nullopt; - } + std::scoped_lock lock(_mutex); + return function(); } - protected: + private: mutable std::mutex _mutex; @@ -175,6 +125,7 @@ namespace armarx::armem::server::wm /// @see base::MemoryBase class Memory : public base::MemoryBase<CoreSegment, Memory> + , public armem::wm::detail::FindInstanceDataMixin<Memory> { using Base = base::MemoryBase<CoreSegment, Memory>; diff --git a/source/RobotAPI/libraries/armem/test/ArMemForEachTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemForEachTest.cpp index cc34f7e2d7cb73d7a3e3715064508c3b73cab351..9c29804ebdc56444b175b3de0abd115b3a1067c0 100644 --- a/source/RobotAPI/libraries/armem/test/ArMemForEachTest.cpp +++ b/source/RobotAPI/libraries/armem/test/ArMemForEachTest.cpp @@ -27,6 +27,7 @@ #include <RobotAPI/Test.h> #include <RobotAPI/libraries/armem/core/Commit.h> #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h> +#include <RobotAPI/libraries/armem/core/operations.h> #include <iostream> #include <set> @@ -98,7 +99,7 @@ BOOST_AUTO_TEST_CASE(test_forEach) BOOST_CHECK_GT(pids.size(), 0); BOOST_CHECK_GT(cids.size(), 0); - BOOST_TEST_MESSAGE("Memory: \n" << memory.dump()); + BOOST_TEST_MESSAGE("Memory: \n" << armem::print(memory)); memory.forEachInstance([&](const wm::EntityInstance & i) -> bool { diff --git a/source/RobotAPI/libraries/armem/test/ArMemMemoryTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemMemoryTest.cpp index 143577fc3303aec2e73c5e7bd6f2c2d7226bc3fd..439f3d8bc338695ad293e8d179ea3f9d100b6ae9 100644 --- a/source/RobotAPI/libraries/armem/test/ArMemMemoryTest.cpp +++ b/source/RobotAPI/libraries/armem/test/ArMemMemoryTest.cpp @@ -499,7 +499,7 @@ struct CopyMoveCtorsOpsTest : public CopyMoveCtorsOpsTestBase || std::is_same_v<T, armem::ltm::Memory> || std::is_same_v<T, armem::d_ltm::Memory>) { - in._addMissingCoreSegmentDuringUpdate = true; + in.addCoreSegment("C"); } { armem::EntityUpdate update; diff --git a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp index 656842b3dcd23d49a84a51a04fc02143c14cada2..b97ac5e3ca5944f4998d70da72fefdd6426efbfc 100644 --- a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp +++ b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp @@ -123,8 +123,9 @@ BOOST_AUTO_TEST_CASE(test_entity_Single_latest) { BOOST_CHECK_EQUAL(result.name(), entity.name()); BOOST_CHECK_EQUAL(result.size(), 1); - const armem::wm::EntitySnapshot& first = result.getFirstSnapshotAfterOrAt(armem::Time::microSeconds(0)); - BOOST_CHECK_EQUAL(first.time(), armem::Time::microSeconds(5000)); + const armem::wm::EntitySnapshot* first = result.findFirstSnapshotAfterOrAt(armem::Time::microSeconds(0)); + BOOST_REQUIRE_NE(first, nullptr); + BOOST_CHECK_EQUAL(first->time(), armem::Time::microSeconds(5000)); } } diff --git a/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp index cd10a49c91957e5fa86094597c7903f76fb04c13..aac9200bc90353c61319e506e34e8e9017d6d445 100644 --- a/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp +++ b/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp @@ -124,8 +124,11 @@ namespace armarx::armem::server::obj::clazz { try { - std::optional<arondto::ObjectClass> aron = - coreSegment->getLatestEntityInstanceDataLockingAs<arondto::ObjectClass>(entityID, 0); + std::optional<arondto::ObjectClass> aron = coreSegment->doLocked([&coreSegment, &entity]() + { + return coreSegment->findLatestInstanceDataAs<arondto::ObjectClass>(entityID, 0); + }); + if (not aron.has_value()) { return;