registrar: add skeleton of plugin registry

This commit is contained in:
Danny Robson 2019-04-16 11:02:26 +10:00
parent 520af37042
commit 0683f80903
4 changed files with 134 additions and 0 deletions

View File

@ -424,6 +424,8 @@ list (
rational.hpp
region.cpp
region.hpp
registrar.cpp
registrar.hpp
roots/bisection.hpp
scoped.hpp
signal.cpp
@ -624,6 +626,7 @@ if (TESTS)
range
rational
region
registrar
roots/bisection
scoped
signal

9
registrar.cpp Normal file
View File

@ -0,0 +1,9 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#include "registrar.hpp"

96
registrar.hpp Normal file
View File

@ -0,0 +1,96 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "log.hpp"
#include "introspection.hpp"
#include <map>
#include <stdexcept>
namespace cruft {
template <typename KeyT, typename FactoryT>
class registry {
public:
struct cookie {
explicit cookie (KeyT const &_key)
: m_key (_key)
{ ; }
explicit cookie (KeyT &&_key)
: m_key (std::move (_key))
{ ; }
cookie (cookie &&rhs) noexcept
: m_key (std::move (rhs.key))
{ ; }
cookie& operator= (cookie &&rhs) noexcept
{
std::swap (rhs.m_key, m_key);
return *this;
}
cookie (cookie const&) = delete;
cookie& operator= (cookie const&) = delete;
~cookie ()
{
registry::remove (m_key);
}
private:
KeyT m_key;
};
static cookie
add [[nodiscard]] (KeyT key, FactoryT &&factory)
{
auto const &[pos, success] = store ().insert (
{ key, std::move (factory) }
);
if (success) {
LOG_INFO ("Registered %! for %!", key, cruft::type_name<FactoryT> ());
return cookie { key };
} {
LOG_ERROR ("Unable to register %! for %!", key, cruft::type_name<FactoryT> ());
throw std::runtime_error ("Unable to register type");
}
}
static FactoryT remove (KeyT const &key)
{
auto &s_factory = store ();
auto pos = s_factory.find (key);
if (pos == s_factory.cend ())
throw std::invalid_argument ("Key not found");
auto val = s_factory.extract (pos);
return std::move (val.mapped ());
}
static FactoryT& at (KeyT const &key)
{
return store ().at (key);
}
private:
static auto&
store (void)
{
static std::map<KeyT,FactoryT> s_factory;
return s_factory;
}
};
}

26
test/registrar.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "registrar.hpp"
#include "tap.hpp"
void foo () { }
int main ()
{
cruft::TAP::logger tap;
using void_fptr = void(*)();
using registry_type = cruft::registry<char const*, void_fptr>;
{
auto cookie = registry_type::add ("foo", foo);
tap.expect_eq (registry_type::at ("foo"), foo, "queried value matches registered value");
}
tap.expect_throw<std::out_of_range> (
[] () { registry_type::at ("foo"); },
"destruction of cookie removes value"
);
return tap.status ();
}