Intel clGPU
container.hpp
1 // Copyright (c) 2017-2018 Intel Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 #include <memory>
17 #include <unordered_map>
18 #include <exception>
19 #include <typeindex>
20 
21 namespace iclgpu
22 {
25 
27 template <class C>
28 class container
29 {
30  class element_base {};
31  using element_id_t = char;
32  using element_key = std::type_index;
33 
34 public:
36  class holder
37  {
38  public:
39  using container_type = C;
40 
41  explicit holder(const std::shared_ptr<C>& ctx)
42  : _context(ctx) {}
43 
44  virtual ~holder() = default;
46  std::shared_ptr<C> context() const { return _context; }
47  private:
48  std::shared_ptr<C> _context;
49  };
50 
52  template <class T>
53  class element : public element_base
54  {
55  public:
56  using container_type = C;
57 
58  explicit element(const std::shared_ptr<C>& ctx)
59  : _context(ctx) {}
60 
61  virtual ~element() = default;
63  std::shared_ptr<C> context() const { return _context.lock(); }
64  private:
65  std::weak_ptr<C> _context;
66 
67  public:
68  element(const element& other) = delete;
69  element(element&& other) noexcept = delete;
70  element& operator=(const element& other) = delete;
71  element& operator=(element&& other) noexcept = delete;
72  };
73 
76  template <class T, typename ... Args>
77  typename std::enable_if<std::is_base_of<element_base, T>::value, std::shared_ptr<T>>::type
78  get(Args&&...args)
79  {
80  element_key key(typeid(T));
81  auto it = _elements.find(key);
82  if (it != _elements.end())
83  {
84  return std::static_pointer_cast<T>(it->second);
85  }
86  auto result = instantiate<T>(std::forward<Args>(args)...);
87  _elements.insert(std::make_pair(key, result));
88  return result;
89  }
90 
92  template <typename T, typename ... Args>
93  typename std::enable_if<std::is_base_of<holder, T>::value, std::shared_ptr<T>>::type
94  get(Args&&...args)
95  {
96  return instantiate<T>(std::forward<Args>(args)...);
97  }
98 
99 private:
100  std::unordered_map<element_key, std::shared_ptr<element_base>> _elements;
101 
102  template<class T, class... Args>
103  std::enable_if_t<std::is_constructible<T, std::shared_ptr<C>, Args&&...>::value, std::shared_ptr<T>>
104  instantiate(Args&&...args)
105  {
106  return std::make_shared<T>(static_cast<C*>(this)->shared_from_this(), std::forward<Args>(args)...);
107  }
108 
109  template<class T, class... Args>
110  std::enable_if_t<!std::is_constructible<T, std::shared_ptr<C>, Args&&...>::value, std::shared_ptr<T>>
111  instantiate(Args&&...args)
112  {
113  throw std::logic_error("Cannot instantiate class.");
114  }
115 };
116 
118 } // namespace iclgpu
Context holder base class.
Definition: container.hpp:36
std::shared_ptr< C > context() const
Get container/context reference.
Definition: container.hpp:63
Base class for service lookup containers.
Definition: container.hpp:28
Base class for objects onwed by container/context.
Definition: container.hpp:53
std::shared_ptr< C > context() const
Get container/context reference.
Definition: container.hpp:46