signal.h Source File - ClanLib SDK
Description: signal.h Source File

signal.h
1/*
2** ClanLib SDK
3** Copyright (c) 1997-2020 The ClanLib Team
4**
5** This software is provided 'as-is', without any express or implied
6** warranty. In no event will the authors be held liable for any damages
7** arising from the use of this software.
8**
9** Permission is granted to anyone to use this software for any purpose,
10** including commercial applications, and to alter it and redistribute it
11** freely, subject to the following restrictions:
12**
13** 1. The origin of this software must not be misrepresented; you must not
14** claim that you wrote the original software. If you use this software
15** in a product, an acknowledgment in the product documentation would be
16** appreciated but is not required.
17** 2. Altered source versions must be plainly marked as such, and must not be
18** misrepresented as being the original software.
19** 3. This notice may not be removed or altered from any source distribution.
20**
21** Note: Some of the libraries ClanLib may link to may have additional
22** requirements or restrictions.
23**
24** File Author(s):
25**
26** Magnus Norddahl
27*/
28
29#pragma once
30
31#include "bind_member.h"
32#include <memory>
33#include <functional>
34#include <vector>
35
36namespace clan
37{
40
41 class SlotImpl;
42
43 class Slot
44 {
45 public:
46 Slot() { }
47
48 operator bool() const { return static_cast<bool>(impl); }
49
50 template<typename T>
51 explicit Slot(T impl) : impl(impl) { }
52
53 private:
54 std::shared_ptr<SlotImpl> impl;
55 };
56
57 class SlotImpl
58 {
59 public:
60 SlotImpl() { }
61 SlotImpl(const SlotImpl &) = delete;
62 SlotImpl &operator=(const SlotImpl &) = delete;
63 virtual ~SlotImpl() { }
64 };
65
66 template<typename SlotImplType>
67 class SignalImpl
68 {
69 public:
70 std::vector<std::weak_ptr<SlotImplType>> slots;
71 };
72
73 template<typename FuncType>
74 class SlotImplT : public SlotImpl
75 {
76 public:
77 SlotImplT(const std::weak_ptr<SignalImpl<SlotImplT>> &signal, const std::function<FuncType> &callback) : signal(signal), callback(callback)
78 {
79 }
80
81 ~SlotImplT()
82 {
83 std::shared_ptr<SignalImpl<SlotImplT>> sig = signal.lock();
84 if (sig)
85 {
86 for (auto it = sig->slots.begin(); it != sig->slots.end(); ++it)
87 {
88 // todo: investigate if "it->lock().get() == this" is required
89 if (it->expired() || it->lock().get() == this)
90 {
91 it = sig->slots.erase(it);
92 if (it == sig->slots.end())
93 break;
94 }
95 }
96 }
97 }
98
99 std::weak_ptr<SignalImpl<SlotImplT>> signal;
100 std::function<FuncType> callback;
101 };
102
103 template<typename FuncType>
104 class Signal
105 {
106 public:
107 Signal() : impl(std::make_shared<SignalImpl<SlotImplT<FuncType>>>()) { }
108
109 template<typename... Args>
110 void operator()(Args&&... args)
111 {
112 std::vector<std::weak_ptr<SlotImplT<FuncType>>> slots = impl->slots;
113 for (std::weak_ptr<SlotImplT<FuncType>> &weak_slot : slots)
114 {
115 std::shared_ptr<SlotImplT<FuncType>> slot = weak_slot.lock();
116 if (slot)
117 {
118 slot->callback(std::forward<Args>(args)...);
119 }
120 }
121 }
122
123 Slot connect(const std::function<FuncType> &func)
124 {
125 auto slot_impl = std::make_shared<SlotImplT<FuncType>>(impl, func);
126 impl->slots.push_back(slot_impl);
127 return Slot(slot_impl);
128 }
129
130 template<typename InstanceType, typename MemberFuncType>
131 Slot connect(InstanceType instance, MemberFuncType func)
132 {
133 return connect(bind_member(instance, func));
134 }
135
136 private:
137 std::shared_ptr<SignalImpl<SlotImplT<FuncType>>> impl;
138 };
139
140 class SlotContainer
141 {
142 public:
143 template<typename FuncType, typename InstanceType, typename MemberFuncType>
144 void connect(Signal<FuncType> &signal, InstanceType instance, MemberFuncType func)
145 {
146 slots.push_back(signal.connect(instance, func));
147 }
148
149 template<typename FuncType, typename CallbackType>
150 void connect(Signal<FuncType> &signal, CallbackType func)
151 {
152 slots.push_back(signal.connect(func));
153 }
154
155 private:
156 std::vector<Slot> slots;
157 };
158
160}
clan::SignalImpl
Definition signal.h:68
clan::SignalImpl::slots
std::vector< std::weak_ptr< SlotImplType > > slots
Definition signal.h:70
clan::Signal
Definition signal.h:105
clan::Signal::operator()
void operator()(Args &&... args)
Definition signal.h:110
clan::Signal::connect
Slot connect(InstanceType instance, MemberFuncType func)
Definition signal.h:131
clan::Signal::connect
Slot connect(const std::function< FuncType > &func)
Definition signal.h:123
clan::Signal::Signal
Signal()
Definition signal.h:107
clan::SlotContainer
Definition signal.h:141
clan::SlotContainer::connect
void connect(Signal< FuncType > &signal, InstanceType instance, MemberFuncType func)
Definition signal.h:144
clan::SlotContainer::connect
void connect(Signal< FuncType > &signal, CallbackType func)
Definition signal.h:150
clan::SlotImplT
Definition signal.h:75
clan::SlotImplT::SlotImplT
SlotImplT(const std::weak_ptr< SignalImpl< SlotImplT > > &signal, const std::function< FuncType > &callback)
Definition signal.h:77
clan::SlotImplT::~SlotImplT
~SlotImplT()
Definition signal.h:81
clan::SlotImplT::signal
std::weak_ptr< SignalImpl< SlotImplT > > signal
Definition signal.h:99
clan::SlotImplT::callback
std::function< FuncType > callback
Definition signal.h:100
clan::SlotImpl
Definition signal.h:58
clan::SlotImpl::SlotImpl
SlotImpl(const SlotImpl &)=delete
clan::SlotImpl::SlotImpl
SlotImpl()
Definition signal.h:60
clan::SlotImpl::operator=
SlotImpl & operator=(const SlotImpl &)=delete
clan::SlotImpl::~SlotImpl
virtual ~SlotImpl()
Definition signal.h:63
clan::Slot
Definition signal.h:44
clan::Slot::Slot
Slot()
Definition signal.h:46
clan::Slot::Slot
Slot(T impl)
Definition signal.h:51
clan::bind_member
std::function< R(Args...)> bind_member(T *instance, R(T::*method)(Args...))
Definition bind_member.h:40
clan
Definition clanapp.h:36