InterfaceList.hpp
1 #ifndef SCORE_INTERFACELIST_2018_10_22
2 #define SCORE_INTERFACELIST_2018_10_22
3 #pragma once
4 #include <score/plugins/Interface.hpp>
5 #include <score/tools/std/IndirectContainer.hpp>
6 #include <score/tools/std/Pointer.hpp>
7 
8 #include <ossia/detail/hash_map.hpp>
9 
10 #include <nano_signal_slot.hpp>
11 #include <score_lib_base_export.h>
12 
13 namespace score
14 {
28 class SCORE_LIB_BASE_EXPORT InterfaceListBase
29 {
30 public:
31  static constexpr bool factory_list_tag = true;
32  InterfaceListBase() noexcept = default;
33  InterfaceListBase(const InterfaceListBase&) = delete;
35  InterfaceListBase& operator=(const InterfaceListBase&) = delete;
36  InterfaceListBase& operator=(InterfaceListBase&&) = delete;
37  virtual ~InterfaceListBase();
38 
40  virtual score::InterfaceKey interfaceKey() const noexcept = 0;
41 
47  virtual void insert(std::unique_ptr<score::InterfaceBase>) = 0;
48 
54  virtual void optimize() noexcept = 0;
55 };
56 
57 SCORE_LIB_BASE_EXPORT void
58 debug_types(const score::InterfaceBase* orig, const score::InterfaceBase* repl) noexcept;
76 template <typename FactoryType>
78  : public score::InterfaceListBase
79  , public IndirectContainer<FactoryType>
80 {
81 public:
82  using factory_type = FactoryType;
83  using key_type = typename FactoryType::ConcreteKey;
85  InterfaceList() = default;
86  ~InterfaceList() = default;
87 
88  static const constexpr score::InterfaceKey static_interfaceKey() noexcept
89  {
90  return FactoryType::static_interfaceKey();
91  }
92 
93  constexpr score::InterfaceKey interfaceKey() const noexcept final override
94  {
95  return FactoryType::static_interfaceKey();
96  }
97 
98  void insert(std::unique_ptr<score::InterfaceBase> e) final override
99  {
100  if(auto result = dynamic_cast<factory_type*>(e.get()))
101  {
102  e.release();
103  std::unique_ptr<factory_type> pf{result};
104  vector_type::push_back(pf.get());
105 
106  auto k = pf->concreteKey();
107  auto it = this->map.find(k);
108  if(it == this->map.end())
109  {
110  this->map.emplace(std::make_pair(k, std::move(pf)));
111  }
112  else
113  {
114  score::debug_types(it->second.get(), result);
115  it->second = std::move(pf);
116  }
117 
118  added(vector_type::back());
119  }
120  }
121 
123  FactoryType* get(const key_type& k) const noexcept
124  {
125  auto it = this->map.find(k);
126  return (it != this->map.end()) ? it->second.get() : nullptr;
127  }
128 
129  mutable Nano::Signal<void(const factory_type&)> added;
130 
131 protected:
132  ossia::hash_map<typename FactoryType::ConcreteKey, std::unique_ptr<FactoryType>> map;
133 
134 private:
135  void optimize() noexcept final override
136  {
137  // score::optimize_hash_map(this->map);
138  this->map.max_load_factor(0.1f);
139  this->map.reserve(map.size());
140  }
141 
142  InterfaceList(const InterfaceList&) = delete;
143  InterfaceList(InterfaceList&&) = delete;
144  InterfaceList& operator=(const InterfaceList&) = delete;
145  InterfaceList& operator=(InterfaceList&&) = delete;
146 };
147 
151 template <typename T>
153 {
154 public:
166  template <typename Fun, typename... Args>
167  auto make(Fun f, Args&&... args) const noexcept
168  {
169  using val_t = decltype(*this->begin());
170  for(const val_t& elt : *this)
171  {
172  if(elt.matches(std::forward<Args>(args)...))
173  {
174  return (elt.*f)(std::forward<Args>(args)...);
175  }
176  }
177  return decltype((std::declval<val_t>().*f)(std::forward<Args>(args)...)){};
178  }
179 };
180 }
181 #endif
Definition: UuidKey.hpp:343
Definition: IndirectContainer.hpp:129
Base class for plug-in interfaces.
Definition: Interface.hpp:52
InterfaceListBase Interface to access factories.
Definition: InterfaceList.hpp:29
virtual score::InterfaceKey interfaceKey() const noexcept=0
A key that uniquely identifies this family of factories.
InterfaceList Default implementation of InterfaceListBase.
Definition: InterfaceList.hpp:80
FactoryType * get(const key_type &k) const noexcept
Get a particular factory from its ConcreteKey.
Definition: InterfaceList.hpp:123
void insert(std::unique_ptr< score::InterfaceBase > e) final override
insert Register a new factory.
Definition: InterfaceList.hpp:98
constexpr score::InterfaceKey interfaceKey() const noexcept final override
A key that uniquely identifies this family of factories.
Definition: InterfaceList.hpp:93
Utility class for making a factory interface list.
Definition: InterfaceList.hpp:153
auto make(Fun f, Args &&... args) const noexcept
Apply a function on the correct factory according to a set of parameter.
Definition: InterfaceList.hpp:167
Base toolkit upon which the software is built.
Definition: Application.cpp:90