File indexing completed on 2026-09-27 09:14:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef LAGER_CORE_FACTORY_LOADED
0021 #define LAGER_CORE_FACTORY_LOADED
0022
0023 #include <map>
0024 #include <memory>
0025 #include <mutex>
0026 #include <lager/core/assert.hh>
0027 #include <lager/core/logger.hh>
0028 #include <string>
0029
0030 namespace lager {
0031
0032
0033 class factory_error : public lager::exception {
0034 public:
0035 factory_error(const std::string& msg,
0036 const std::string& type = "factory_error")
0037 : lager::exception{msg, type} {}
0038 };
0039 class factory_key_error : public factory_error {
0040 public:
0041 factory_key_error(const std::string& msg)
0042 : factory_error{msg, "factory_key_error"} {}
0043 };
0044
0045
0046 #define FACTORY_REGISTER(gen, class, name) \
0047 namespace { \
0048 struct proxy_##class { \
0049 proxy_##class() { gen::factory_instance.add<class>(name); } \
0050 }; \
0051 const proxy_##class p_##class; \
0052 }
0053 #define FACTORY_REGISTER2(gen, class, name) \
0054 gen::factory_instance.add<class>(name)
0055
0056
0057 #define FACTORY_CREATE(gen, conf, path, rng) \
0058 gen::factory_instance.create( \
0059 conf.get<std::string>(string_path(path) / "type"), conf, path, rng)
0060
0061
0062 template <class T, class... Args> class factory {
0063 private:
0064 struct worker_base;
0065 using worker_map_type = std::map<std::string, std::shared_ptr<worker_base>>;
0066
0067 public:
0068 std::shared_ptr<T> create(const std::string& name, Args... a) const {
0069
0070
0071
0072 LOG_DEBUG("factory", "Constructing " + name);
0073 if (!workers_) {
0074 LOG_DEBUG("factory",
0075 "Worker pointer is a null pointer. This should never happen.");
0076 }
0077 if (!workers_ || !workers_->count(name)) {
0078 LOG_ERROR("factory", "Cannot construct object " + name +
0079 ": no such name registered.");
0080 throw factory_key_error{"Failed to construct object."};
0081 }
0082 return workers_->find(name)->second->create(a...);
0083 }
0084
0085 template <class U> void add(const std::string& name) {
0086
0087
0088
0089
0090
0091 std::lock_guard<std::mutex> lock{mutex_};
0092 LOG_DEBUG("factory", "Registered class: " + name);
0093 if (!workers_) {
0094 workers_ = std::make_unique<worker_map_type>();
0095 }
0096 workers_->insert(std::make_pair(name, std::make_shared<worker<U>>()));
0097 }
0098
0099 void remove(const std::string& name) {
0100 std::lock_guard<std::mutex> lock{mutex_};
0101 if (!workers_ || !workers_->count(name)) {
0102 LOG_ERROR("factory", "Cannot remove worker for class " + name +
0103 ": no such name registered.");
0104 throw factory_key_error{"Failed to remove worker."};
0105 }
0106 workers_.erase(name);
0107 }
0108
0109 private:
0110
0111 struct worker_base {
0112 virtual std::shared_ptr<T> create(Args...) const = 0;
0113 };
0114 template <class U> struct worker : worker_base {
0115 virtual std::shared_ptr<T> create(Args... a) const {
0116 return std::make_shared<U>(a...);
0117 }
0118 };
0119
0120 std::unique_ptr<worker_map_type> workers_;
0121 mutable std::mutex mutex_;
0122 };
0123
0124 }
0125
0126 #endif