Skip to content

Instantly share code, notes, and snippets.

@gmbeard
Created November 1, 2015 20:31
Show Gist options
  • Save gmbeard/b3d20443f57318440515 to your computer and use it in GitHub Desktop.
Save gmbeard/b3d20443f57318440515 to your computer and use it in GitHub Desktop.
A simple "Service Manager" implementation
#include <iostream>
#include <unordered_map>
#include <memory>
#ifdef _DEBUG
#include <cassert>
#endif
namespace gmb
{
struct service_id { };
struct service
{
service(std::string const &name)
: name_(name)
{ }
const std::string & name() const
{
return name_;
}
private:
std::string name_;
};
struct dummy_service : service
{
dummy_service()
: service("Dummy Service")
{ }
static constexpr service_id id = {};
};
constexpr service_id dummy_service::id;
struct my_service : service
{
my_service()
: service("My Service")
{ }
static constexpr service_id id = {};
};
constexpr service_id my_service::id;
struct another_service : service
{
another_service()
: service("Another Service")
{ }
static constexpr service_id id = {};
};
constexpr service_id another_service::id;
using service_map = std::unordered_map<service_id const *, std::unique_ptr<service>>;
template<typename Service>
void add_service(std::unique_ptr<Service> svc, service_map &svc_map)
{
svc_map[&Service::id] = std::move(svc);
}
template<typename Service>
bool has_service(service_map const &svc_map)
noexcept(noexcept(svc_map.find(&Service::id)))
{
return (std::end(svc_map) != svc_map.find(&Service::id));
}
template<typename Service>
Service * get_service(service_map const &svc_map)
{
return svc_map.at(&Service::id).get();
}
template<typename Service>
std::unique_ptr<Service> remove_service(service_map &svc_map)
{
std::unique_ptr<Service> p(static_cast<Service *>(svc_map.at(&Service::id).release()));
svc_map.erase(&Service::id);
return std::move(p);
}
}
int main(int, char const *[])
{
using namespace gmb;
service_map services;
auto a = std::make_unique<my_service>();
auto b = std::make_unique<another_service>();
add_service(std::move(a), services);
add_service(std::move(b), services);
assert(has_service<decltype(b)::element_type>(services));
assert(has_service<decltype(a)::element_type>(services));
assert(!has_service<dummy_service>(services));
a = remove_service<decltype(a)::element_type>(services);
b = remove_service<decltype(b)::element_type>(services);
try {
remove_service<dummy_service>(services);
assert(false);
}
catch(...) { }
assert(a);
assert(b);
return 0;
}
@gmbeard
Copy link
Author

gmbeard commented Nov 1, 2015

Simple Service Manager

Description

We can add our own services to this simple manager by deriving a service type from gmb::service and implementing a static gmb::service_id member named id.

Compile with -D_DEBUG (or /D _DEBUG for VC++)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment