kodi
Signals.h
1 /*
2  * Copyright (C) 2017-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "threads/CriticalSection.h"
12 
13 #include <map>
14 #include <memory>
15 #include <mutex>
16 
17 namespace KODI
18 {
19 
20 using RegistrationIdentifierType = int;
21 
23 {
24 protected:
25  ~ISignalHandlerData() = default;
26 
27 public:
28  virtual void Unregister(RegistrationIdentifierType id) = 0;
29 };
30 
32 {
33  std::weak_ptr<ISignalHandlerData> m_list;
34  RegistrationIdentifierType m_registration;
35 
36  template<typename ManagedT>
37  friend class CSignalHandlerList;
38 
39  CSignalRegistration(std::shared_ptr<ISignalHandlerData> const& list, RegistrationIdentifierType registration)
40  : m_list{list}, m_registration{registration}
41  {
42  }
43 
44  CSignalRegistration(CSignalRegistration const& other) = delete;
45  CSignalRegistration& operator=(CSignalRegistration const& other) = delete;
46 
47 public:
48  CSignalRegistration() noexcept = default;
49 
51  {
52  *this = std::move(other);
53  }
54 
55  inline CSignalRegistration& operator=(CSignalRegistration&& other) noexcept
56  {
57  Unregister();
58  std::swap(m_list, other.m_list);
59  m_registration = other.m_registration;
60  return *this;
61  }
62 
63  ~CSignalRegistration() noexcept
64  {
65  Unregister();
66  }
67 
68  inline void Unregister()
69  {
70  if (auto list = m_list.lock())
71  {
72  list->Unregister(m_registration);
73  list.reset();
74  }
75  }
76 };
77 
78 template<typename ManagedT>
80 {
87  struct Data final : public ISignalHandlerData
88  {
89  CCriticalSection m_handlerCriticalSection;
90  std::map<RegistrationIdentifierType, ManagedT> m_handlers;
91 
92  void Unregister(RegistrationIdentifierType id) override
93  {
94  std::unique_lock<CCriticalSection> lock(m_handlerCriticalSection);
95  m_handlers.erase(id);
96  }
97  };
98 
99  std::shared_ptr<Data> m_data;
100  RegistrationIdentifierType m_lastRegistrationId{};
101 
102  CSignalHandlerList(CSignalHandlerList const& other) = delete;
103  CSignalHandlerList& operator=(CSignalHandlerList const& other) = delete;
104 
105 public:
107  : m_data{new Data}
108  {}
109 
110  CSignalRegistration Register(ManagedT const& handler)
111  {
112  std::unique_lock<CCriticalSection> lock(m_data->m_handlerCriticalSection);
113  bool inserted{false};
114  while(!inserted)
115  {
116  inserted = m_data->m_handlers.emplace(++m_lastRegistrationId, handler).second;
117  }
118  return {m_data, m_lastRegistrationId};
119  }
120 
126  template<typename... ArgsT>
127  void Invoke(ArgsT&&... args)
128  {
129  std::unique_lock<CCriticalSection> lock(m_data->m_handlerCriticalSection);
130  for (auto const& handler : *this)
131  {
132  handler.second(std::forward<ArgsT>(args)...);
133  }
134  }
135 
136  auto begin() const { return m_data->m_handlers.cbegin(); }
137 
138  auto end() const { return m_data->m_handlers.cend(); }
139 
145  CCriticalSection const& CriticalSection() const
146  {
147  return m_data->m_handlerCriticalSection;
148  }
149 };
150 
151 }
void Invoke(ArgsT &&... args)
Invoke all registered signal handlers with the provided arguments when the signal type is a std::func...
Definition: Signals.h:127
CCriticalSection const & CriticalSection() const
Get critical section for accessing the handler list.
Definition: Signals.h:145
Definition: AudioDecoder.h:18
Definition: Signals.h:79
Definition: Signals.h:22
Definition: Signals.h:31