diff --git a/include/name_mapper.h b/include/name_mapper.h index 3df594c12..3c9d4b96e 100644 --- a/include/name_mapper.h +++ b/include/name_mapper.h @@ -22,6 +22,8 @@ #include #include +#include +#include namespace kiwix { @@ -54,7 +56,24 @@ class HumanReadableNameMapper : public NameMapper { virtual std::string getIdForName(const std::string& name); }; +class NameMapperProxy : public kiwix::NameMapper { + typedef std::shared_ptr NameMapperHandle; + public: + explicit NameMapperProxy(kiwix::Library& library); + + virtual std::string getNameForId(const std::string& id); + virtual std::string getIdForName(const std::string& name); + + void update(); + private: + NameMapperHandle currentNameMapper() const; + + private: + mutable std::mutex mutex; + kiwix::Library& library; + NameMapperHandle nameMapper; +}; } diff --git a/src/name_mapper.cpp b/src/name_mapper.cpp index 394e329d0..4e335fc00 100644 --- a/src/name_mapper.cpp +++ b/src/name_mapper.cpp @@ -59,4 +59,45 @@ std::string HumanReadableNameMapper::getIdForName(const std::string& name) { 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) +{ + // 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) +{ + // Ensure that the current nameMapper object survives a concurrent call + // to NameMapperProxy::update() + return currentNameMapper()->getIdForName(name); +} + }