Skip to content
Snippets Groups Projects
Commit ec477459 authored by Rainer Kartmann's avatar Rainer Kartmann
Browse files

Revise locking interface

parent d8d0b333
No related branches found
No related tags found
3 merge requests!192Fix bugs in ArMem and make disk loading and storing nicer,!190ArMem: Revice get/find interface,!188ArMem Updates
Showing
with 81 additions and 179 deletions
...@@ -111,8 +111,10 @@ namespace armarx::armem::server ...@@ -111,8 +111,10 @@ namespace armarx::armem::server
MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const armem::server::wm::CoreSegment& coreSegment) const MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const armem::server::wm::CoreSegment& coreSegment) const
{ {
std::scoped_lock lock(coreSegment.mutex()); return coreSegment.doLocked([this, &coreSegment]()
return this->_makeGroupBox(coreSegment); {
return this->_makeGroupBox(coreSegment);
});
} }
......
...@@ -60,20 +60,22 @@ namespace armarx::armem::server ...@@ -60,20 +60,22 @@ namespace armarx::armem::server
if (input.providerSegmentName.size() > 0) if (input.providerSegmentName.size() > 0)
{ {
std::scoped_lock lock(coreSegment->mutex()); coreSegment->doLocked([&coreSegment, &input]()
try
{
coreSegment->addProviderSegment(input.providerSegmentName);
}
catch (const armem::error::ContainerEntryAlreadyExists&)
{ {
// This is ok. try
if (input.clearWhenExists)
{ {
server::wm::ProviderSegment& provider = coreSegment->getProviderSegment(input.providerSegmentName); coreSegment->addProviderSegment(input.providerSegmentName);
provider.clear();
} }
} catch (const armem::error::ContainerEntryAlreadyExists&)
{
// This is ok.
if (input.clearWhenExists)
{
server::wm::ProviderSegment& provider = coreSegment->getProviderSegment(input.providerSegmentName);
provider.clear();
}
}
});
} }
armem::MemoryID segmentID; armem::MemoryID segmentID;
......
...@@ -55,8 +55,10 @@ namespace armarx::armem::server::query_proc::wm_server ...@@ -55,8 +55,10 @@ namespace armarx::armem::server::query_proc::wm_server
const armem::query::data::CoreSegmentQuery& query, const armem::query::data::CoreSegmentQuery& query,
const CoreSegment& coreSegment) const const CoreSegment& coreSegment) const
{ {
std::scoped_lock lock(coreSegment.mutex()); coreSegment.doLocked([&]()
CoreSegmentQueryProcessorBase::process(result, query, coreSegment); {
CoreSegmentQueryProcessorBase::process(result, query, coreSegment);
});
} }
......
...@@ -48,14 +48,6 @@ namespace armarx::armem::server::segment ...@@ -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( wm::ProviderSegmentBase::ProviderSegmentBase(
armem::server::MemoryToIceAdapter& iceMemory, armem::server::MemoryToIceAdapter& iceMemory,
const std::string& defaultProviderSegmentName, const std::string& defaultProviderSegmentName,
......
#pragma once #pragma once
// STD/STL #include <RobotAPI/libraries/armem/server/forward_declarations.h>
#include <mutex> #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
#include <string>
#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h>
// ArmarX
#include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/logging/Logging.h>
#include <ArmarXCore/core/application/properties/forward_declarations.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 armarx::armem::server::segment
{ {
namespace detail namespace detail
...@@ -88,7 +75,11 @@ namespace armarx::armem::server::segment ...@@ -88,7 +75,11 @@ namespace armarx::armem::server::segment
// virtual void onConnect() override; // virtual void onConnect() override;
std::mutex& mutex() const; template <class FunctionT>
auto doLocked(FunctionT&& function)
{
return segment->doLocked(function);
}
protected: protected:
......
...@@ -12,11 +12,11 @@ namespace armarx::armem::server::segment ...@@ -12,11 +12,11 @@ namespace armarx::armem::server::segment
{ {
SpecializedSegment::SpecializedSegment( SpecializedSegment::SpecializedSegment(
server::MemoryToIceAdapter& iceMemory, server::MemoryToIceAdapter& iceMemory,
aron::typenavigator::ObjectNavigatorPtr aronType, aron::typenavigator::ObjectNavigatorPtr aronType,
const std::string& defaultCoreSegmentName, const std::string& defaultCoreSegmentName,
int64_t defaultMaxHistorySize int64_t defaultMaxHistorySize
) : ) :
iceMemory(iceMemory), aronType(aronType) iceMemory(iceMemory), aronType(aronType)
{ {
setDefaultCoreSegmentName(defaultCoreSegmentName); setDefaultCoreSegmentName(defaultCoreSegmentName);
...@@ -52,13 +52,6 @@ namespace armarx::armem::server::segment ...@@ -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) void SpecializedSegment::setDefaultCoreSegmentName(const std::string& coreSegmentName)
{ {
this->properties.coreSegmentName = coreSegmentName; this->properties.coreSegmentName = coreSegmentName;
......
#pragma once #pragma once
#include <mutex> #include <RobotAPI/libraries/armem/server/forward_declarations.h>
#include <string> #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/application/properties/forward_declarations.h>
#include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/logging/Logging.h>
#include <RobotAPI/libraries/aron/core/navigator/type/forward_declarations.h> #include <string>
namespace armarx::armem
{
namespace server
{
class MemoryToIceAdapter;
namespace wm
{
class CoreSegment;
}
}
}
namespace armarx::armem::server::segment namespace armarx::armem::server::segment
{ {
...@@ -46,7 +34,12 @@ namespace armarx::armem::server::segment ...@@ -46,7 +34,12 @@ namespace armarx::armem::server::segment
virtual void init(); virtual void init();
// void connect(); // void connect();
std::mutex& mutex() const;
template <class FunctionT>
auto doLocked(FunctionT&& function)
{
return coreSegment->doLocked(function);
}
protected: protected:
......
...@@ -43,36 +43,6 @@ namespace armarx::armem::server::wm ...@@ -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 // TODO: add core segment if param is set
std::vector<Memory::Base::UpdateResult> std::vector<Memory::Base::UpdateResult>
Memory::updateLocking(const Commit& commit) Memory::updateLocking(const Commit& commit)
...@@ -95,15 +65,16 @@ namespace armarx::armem::server::wm ...@@ -95,15 +65,16 @@ namespace armarx::armem::server::wm
CoreSegment& coreSegment = it->second; CoreSegment& coreSegment = it->second;
// Lock the core segment for the whole batch. // Lock the core segment for the whole batch.
std::scoped_lock lock(coreSegment.mutex()); coreSegment.doLocked([&result, &coreSegment, updates = &updates]()
for (const EntityUpdate* update : updates)
{ {
auto r = coreSegment.update(*update); for (const EntityUpdate* update : *updates)
Base::UpdateResult ret { r }; {
ret.memoryUpdateType = UpdateType::UpdatedExisting; auto r = coreSegment.update(*update);
result.push_back(ret); Base::UpdateResult ret { r };
} ret.memoryUpdateType = UpdateType::UpdatedExisting;
result.push_back(ret);
}
});
} }
else else
{ {
...@@ -129,10 +100,10 @@ namespace armarx::armem::server::wm ...@@ -129,10 +100,10 @@ namespace armarx::armem::server::wm
CoreSegment& segment = getCoreSegment(update.entityID.coreSegmentName); CoreSegment& segment = getCoreSegment(update.entityID.coreSegmentName);
Base::UpdateResult result; Base::UpdateResult result;
segment.doLocked([&result, &segment, &update]()
{ {
std::scoped_lock lock(segment.mutex());
result = segment.update(update); result = segment.update(update);
} });
result.memoryUpdateType = UpdateType::UpdatedExisting; result.memoryUpdateType = UpdateType::UpdatedExisting;
return result; return result;
} }
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <RobotAPI/libraries/armem/core/base/CoreSegmentBase.h> #include <RobotAPI/libraries/armem/core/base/CoreSegmentBase.h>
#include <RobotAPI/libraries/armem/core/base/MemoryBase.h> #include <RobotAPI/libraries/armem/core/base/MemoryBase.h>
#include <RobotAPI/libraries/armem/core/wm/detail/data_lookup_mixins.h>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
...@@ -28,6 +30,7 @@ namespace armarx::armem::server::wm ...@@ -28,6 +30,7 @@ namespace armarx::armem::server::wm
class Entity : class Entity :
public base::EntityBase<EntitySnapshot, Entity> public base::EntityBase<EntitySnapshot, Entity>
, public detail::MaxHistorySize , public detail::MaxHistorySize
, public armem::wm::detail::FindInstanceDataMixin<Entity>
{ {
public: public:
...@@ -55,8 +58,9 @@ namespace armarx::armem::server::wm ...@@ -55,8 +58,9 @@ namespace armarx::armem::server::wm
/// @see base::ProviderSegmentBase /// @see base::ProviderSegmentBase
class ProviderSegment : class ProviderSegment :
public base::ProviderSegmentBase<Entity, ProviderSegment>, public base::ProviderSegmentBase<Entity, ProviderSegment>
public detail::MaxHistorySizeParent<ProviderSegment> , public detail::MaxHistorySizeParent<ProviderSegment>
, public armem::wm::detail::FindInstanceDataMixin<ProviderSegment>
{ {
public: public:
...@@ -81,6 +85,7 @@ namespace armarx::armem::server::wm ...@@ -81,6 +85,7 @@ namespace armarx::armem::server::wm
class CoreSegment : class CoreSegment :
public base::CoreSegmentBase<ProviderSegment, CoreSegment>, public base::CoreSegmentBase<ProviderSegment, CoreSegment>,
public detail::MaxHistorySizeParent<CoreSegment> public detail::MaxHistorySizeParent<CoreSegment>
, public armem::wm::detail::FindInstanceDataMixin<CoreSegment>
{ {
using Base = base::CoreSegmentBase<ProviderSegment, CoreSegment>; using Base = base::CoreSegmentBase<ProviderSegment, CoreSegment>;
...@@ -88,38 +93,6 @@ namespace armarx::armem::server::wm ...@@ -88,38 +93,6 @@ namespace armarx::armem::server::wm
using Base::CoreSegmentBase; 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() /// @see base::CoreSegmentBase::addProviderSegment()
using CoreSegmentBase::addProviderSegment; using CoreSegmentBase::addProviderSegment;
template <class ...Args> template <class ...Args>
...@@ -133,38 +106,15 @@ namespace armarx::armem::server::wm ...@@ -133,38 +106,15 @@ namespace armarx::armem::server::wm
// Locking interface // Locking interface
std::optional<wm::EntitySnapshot> getLatestEntitySnapshotLocking( template <class FunctionT>
const MemoryID& entityID) const; auto doLocked(FunctionT&& function) 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
{ {
// Keep lock to a minimum. std::scoped_lock lock(_mutex);
wm::EntityInstanceDataPtr data = nullptr; return function();
{
std::scoped_lock lock(_mutex);
data = getLatestEntityInstanceData(entityID, instanceIndex);
}
if (data)
{
AronDtoT aron;
aron.fromAron(data);
return aron;
}
else
{
return std::nullopt;
}
} }
protected: private:
mutable std::mutex _mutex; mutable std::mutex _mutex;
...@@ -175,6 +125,7 @@ namespace armarx::armem::server::wm ...@@ -175,6 +125,7 @@ namespace armarx::armem::server::wm
/// @see base::MemoryBase /// @see base::MemoryBase
class Memory : class Memory :
public base::MemoryBase<CoreSegment, Memory> public base::MemoryBase<CoreSegment, Memory>
, public armem::wm::detail::FindInstanceDataMixin<Memory>
{ {
using Base = base::MemoryBase<CoreSegment, Memory>; using Base = base::MemoryBase<CoreSegment, Memory>;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <RobotAPI/Test.h> #include <RobotAPI/Test.h>
#include <RobotAPI/libraries/armem/core/Commit.h> #include <RobotAPI/libraries/armem/core/Commit.h>
#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h> #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
#include <RobotAPI/libraries/armem/core/operations.h>
#include <iostream> #include <iostream>
#include <set> #include <set>
...@@ -98,7 +99,7 @@ BOOST_AUTO_TEST_CASE(test_forEach) ...@@ -98,7 +99,7 @@ BOOST_AUTO_TEST_CASE(test_forEach)
BOOST_CHECK_GT(pids.size(), 0); BOOST_CHECK_GT(pids.size(), 0);
BOOST_CHECK_GT(cids.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 memory.forEachInstance([&](const wm::EntityInstance & i) -> bool
{ {
......
...@@ -499,7 +499,7 @@ struct CopyMoveCtorsOpsTest : public CopyMoveCtorsOpsTestBase ...@@ -499,7 +499,7 @@ struct CopyMoveCtorsOpsTest : public CopyMoveCtorsOpsTestBase
|| std::is_same_v<T, armem::ltm::Memory> || std::is_same_v<T, armem::ltm::Memory>
|| std::is_same_v<T, armem::d_ltm::Memory>) || std::is_same_v<T, armem::d_ltm::Memory>)
{ {
in._addMissingCoreSegmentDuringUpdate = true; in.addCoreSegment("C");
} }
{ {
armem::EntityUpdate update; armem::EntityUpdate update;
......
...@@ -123,8 +123,9 @@ BOOST_AUTO_TEST_CASE(test_entity_Single_latest) ...@@ -123,8 +123,9 @@ BOOST_AUTO_TEST_CASE(test_entity_Single_latest)
{ {
BOOST_CHECK_EQUAL(result.name(), entity.name()); BOOST_CHECK_EQUAL(result.name(), entity.name());
BOOST_CHECK_EQUAL(result.size(), 1); BOOST_CHECK_EQUAL(result.size(), 1);
const armem::wm::EntitySnapshot& first = result.getFirstSnapshotAfterOrAt(armem::Time::microSeconds(0)); const armem::wm::EntitySnapshot* first = result.findFirstSnapshotAfterOrAt(armem::Time::microSeconds(0));
BOOST_CHECK_EQUAL(first.time(), armem::Time::microSeconds(5000)); BOOST_REQUIRE_NE(first, nullptr);
BOOST_CHECK_EQUAL(first->time(), armem::Time::microSeconds(5000));
} }
} }
......
...@@ -124,8 +124,11 @@ namespace armarx::armem::server::obj::clazz ...@@ -124,8 +124,11 @@ namespace armarx::armem::server::obj::clazz
{ {
try try
{ {
std::optional<arondto::ObjectClass> aron = std::optional<arondto::ObjectClass> aron = coreSegment->doLocked([&coreSegment, &entity]()
coreSegment->getLatestEntityInstanceDataLockingAs<arondto::ObjectClass>(entityID, 0); {
return coreSegment->findLatestInstanceDataAs<arondto::ObjectClass>(entityID, 0);
});
if (not aron.has_value()) if (not aron.has_value())
{ {
return; return;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment