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

Change wm::Memory::commit() to run updates and lock per core segment

parent 276312cf
No related branches found
No related tags found
2 merge requests!185Clean up interfaces and unneeded code in memory core classes,!178Draft: Make RobotStateMemory ready
......@@ -223,7 +223,7 @@ namespace armarx::armem::base
* @param commit The commit.
* @return The resulting memory IDs.
*/
std::vector<UpdateResult> update(const Commit& commit)
virtual std::vector<UpdateResult> update(const Commit& commit)
{
std::vector<UpdateResult> results;
for (const auto& update : commit.updates)
......
#include "Memory.h"
#include <map>
#include <vector>
namespace armarx::armem::wm
{
std::vector<Memory::Base::UpdateResult>
Memory::update(const Commit& commit)
{
// Group updates by core segment, then update each core segment in a batch to only lock it once.
std::map<std::string, std::vector<const EntityUpdate*>> updatesPerCoreSegment;
for (const EntityUpdate& update : commit.updates)
{
updatesPerCoreSegment[update.entityID.coreSegmentName].push_back(&update);
}
std::vector<Memory::Base::UpdateResult> result;
// To throw an exception after the commit if a core segment is missing.
std::vector<std::string> missingCoreSegmentNames;
for (const auto& [coreSegmentName, updates] : updatesPerCoreSegment)
{
auto it = this->_container.find(coreSegmentName);
if (it != this->_container.end())
{
CoreSegment& coreSegment = it->second;
// Lock the core segment for the whole batch.
std::scoped_lock lock(coreSegment.mutex());
for (const EntityUpdate* update : updates)
{
auto r = coreSegment.update(*update);
Base::UpdateResult ret { r };
ret.memoryUpdateType = UpdateType::UpdatedExisting;
result.push_back(ret);
}
}
else
{
// Perform the other updates first, then throw afterwards.
missingCoreSegmentNames.push_back(coreSegmentName);
}
}
// Throw an exception if something went wrong.
if (not missingCoreSegmentNames.empty())
{
// Just throw an exception for the first entry. We can extend this exception in the future.
throw armem::error::MissingEntry::create<CoreSegment>(missingCoreSegmentNames.front(), *this);
}
return result;
}
Memory::Base::UpdateResult Memory::update(const EntityUpdate& update)
{
this->_checkContainerName(update.entityID.memoryName, this->name());
......@@ -25,6 +74,7 @@ namespace armarx::armem::wm
}
}
Commit Memory::toCommit() const
{
Commit c;
......@@ -35,6 +85,7 @@ namespace armarx::armem::wm
return c;
}
void Memory::_copySelfWithoutData(Memory& other) const
{
other.id() = _id;
......@@ -43,4 +94,5 @@ namespace armarx::armem::wm
other.addCoreSegment(s.copyWithoutData());
}
}
}
......@@ -28,6 +28,16 @@ namespace armarx::armem::wm
Memory& operator=(Memory&& other) = default;
/**
* @brief Perform the commit, locking the core segments.
*
* Groups the commits by core segment, and updates each core segment
* in a batch, locking the core segment.
*/
virtual std::vector<Base::UpdateResult> update(const Commit& commit) override;
/**
* @brief Update the memory, locking the updated core segment.
*/
virtual Base::UpdateResult update(const EntityUpdate& update) override;
......
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