diff --git a/include/name_mapper.h b/include/name_mapper.h index 247a19b9f..e7770865b 100644 --- a/include/name_mapper.h +++ b/include/name_mapper.h @@ -22,6 +22,8 @@ #include #include +#include +#include namespace kiwix { @@ -54,6 +56,25 @@ class HumanReadableNameMapper : public NameMapper { virtual std::string getIdForName(const std::string& name) const; }; +class NameMapperProxy : public NameMapper { + typedef std::shared_ptr NameMapperHandle; + public: + explicit NameMapperProxy(Library& library); + + virtual std::string getNameForId(const std::string& id) const; + virtual std::string getIdForName(const std::string& name) const; + + void update(); + + private: + NameMapperHandle currentNameMapper() const; + + private: + mutable std::mutex mutex; + Library& library; + NameMapperHandle nameMapper; +}; + } #endif diff --git a/src/name_mapper.cpp b/src/name_mapper.cpp index d700f4310..b7ec24493 100644 --- a/src/name_mapper.cpp +++ b/src/name_mapper.cpp @@ -59,4 +59,45 @@ std::string HumanReadableNameMapper::getIdForName(const std::string& name) const return m_nameToId.at(name); } +//////////////////////////////////////////////////////////////////////////////// +// NameMapperProxy +//////////////////////////////////////////////////////////////////////////////// + +NameMapperProxy::NameMapperProxy(Library& lib) + : library(lib) +{ + update(); +} + +void NameMapperProxy::update() +{ + const auto newNameMapper = new HumanReadableNameMapper(library, false); + std::lock_guard lock(mutex); + nameMapper.reset(newNameMapper); +} + +NameMapperProxy::NameMapperHandle +NameMapperProxy::currentNameMapper() const +{ + // Return a copy of the handle to the current NameMapper object. It will + // ensure that the object survives any call to NameMapperProxy::update() + // made before the completion of any pending operation on that object. + std::lock_guard lock(mutex); + return nameMapper; +} + +std::string NameMapperProxy::getNameForId(const std::string& id) const +{ + // Ensure that the current nameMapper object survives a concurrent call + // to NameMapperProxy::update() + return currentNameMapper()->getNameForId(id); +} + +std::string NameMapperProxy::getIdForName(const std::string& name) const +{ + // Ensure that the current nameMapper object survives a concurrent call + // to NameMapperProxy::update() + return currentNameMapper()->getIdForName(name); +} + }