5 #include <unordered_map> 9 template <
typename... Ts>
12 using key_type = size_t;
16 : pimpl_{std::make_shared<impl>()} {}
21 event& operator=(
const event&) =
delete;
22 event& operator=(
event&&) noexcept =
default;
24 ~
event() noexcept =
default;
26 using callback_type = std::function<void(Ts...)>;
31 connection(
const std::shared_ptr<impl>& pimpl, callback_type callback)
33 , key_{pimpl->connect(std::move(callback))} {}
37 swap(pimpl_, other.pimpl_);
38 swap(key_, other.key_);
51 if (
auto p = pimpl_.lock()) {
58 if (
auto p = pimpl_.lock()) {
64 if (
auto p = pimpl_.lock()) {
69 explicit operator bool()
const {
return !pimpl_.expired(); }
72 std::weak_ptr<impl> pimpl_;
80 : connection{std::move(connection)} {}
91 connection connection;
94 auto connect(callback_type callback) {
95 return connection{pimpl_, std::move(callback)};
98 template <
typename... Us>
99 void operator()(Us&&... us)
const {
100 pimpl_->operator()(std::forward<Us>(us)...);
103 bool empty()
const {
return pimpl_->empty(); }
104 size_t size()
const {
return pimpl_->size(); }
108 struct callback_info final {
109 callback_type callback;
116 impl(
const impl&) =
delete;
117 impl(impl&&) noexcept =
delete;
119 impl& operator=(
const impl&) =
delete;
120 impl& operator=(impl&&) noexcept =
delete;
122 auto connect(callback_type callback) {
123 std::lock_guard<std::mutex> lck{mutex_};
124 slots_.insert(std::make_pair(++current_key_,
125 callback_info{std::move(callback)}));
129 void disconnect(key_type key) {
130 std::lock_guard<std::mutex> lck{mutex_};
134 void block(key_type key) {
135 std::lock_guard<std::mutex> lck{mutex_};
136 auto slot = slots_.find(key);
137 if (slot != end(slots_)) {
138 slot->second.blocked =
true;
142 void unblock(key_type key) {
143 std::lock_guard<std::mutex> lck{mutex_};
144 auto slot = slots_.find(key);
145 if (slot != end(slots_)) {
146 slot->second.blocked =
false;
150 bool blocked(key_type key)
const {
151 std::lock_guard<std::mutex> lck{mutex_};
152 auto slot = slots_.find(key);
153 if (slot != end(slots_)) {
154 return slot->second.blocked;
156 throw std::logic_error{
"No such key."};
159 template <
typename... Us>
160 void operator()(Us&&... us)
const {
161 std::unordered_map<key_type, callback_info> copy;
164 std::lock_guard<std::mutex> lck{mutex_};
168 for (
const auto& slot : copy) {
169 if (!slot.second.blocked) {
170 slot.second.callback(std::forward<Us>(us)...);
176 std::lock_guard<std::mutex> lck{mutex_};
177 return slots_.empty();
180 size_t size()
const {
181 std::lock_guard<std::mutex> lck{mutex_};
182 return slots_.size();
186 mutable std::mutex mutex_;
188 key_type current_key_{0};
189 std::unordered_map<key_type, callback_info> slots_;
192 std::shared_ptr<impl> pimpl_;
Definition: allocator.h:6