cgv
Loading...
Searching...
No Matches
abst_signal.cxx
1#ifndef NDEBUG
2# include <iostream>
3#endif
4
5#include <algorithm>
6
7#include <cgv/signal/abst_signal.h>
8#include "signal.h"
9
10
11#define MSG_ERROR "\x1b[1;31m[error]\x1b[39m[cgv::signal]\x1b[m"
12
13
14namespace cgv {
15 namespace signal {
16
17void connect(signal<>& s, void(*fp)())
18{
19 s.connect(function_functor<0>(fp));
20}
21
22void disconnect(signal<>& s, void(*fp)())
23{
24 s.disconnect(function_functor<0>(fp));
25}
26
27signal_base::~signal_base() noexcept
28{
29 disconnect_all();
30}
31
33void signal_base::connect_abst(functor_base* fp)
34{
35 connect(fp);
36}
37
38void signal_base::link(receiver& rcvr)
39{
40 if (rcvr.tacker_ptr)
41 rcvr.tacker_ptr->tack(this);
42}
43
44void signal_base::unlink(receiver& rcvr)
45{
46 if (rcvr.tacker_ptr)
47 rcvr.tacker_ptr->untack(this);
48}
49
50void signal_base::connect(functor_base* fp)
51{
52 receivers.push_back({std::unique_ptr<functor_base>{fp}, fp->get_tacker()});
53 link(receivers.back());
54}
55
56void signal_base::disconnect(const functor_base* fp)
57{
58 auto found = false;
59 receivers.erase(std::remove_if(receivers.begin(), receivers.end(), [this, &found, fp](receiver& rcvr) {
60 if(*rcvr.functor == *fp) {
61 found = true;
62 unlink(rcvr);
63 return true;
64 }
65 return false;
66 }), receivers.end());
67
68 #ifndef NDEBUG
69 if (!found)
70 std::cerr << MSG_ERROR" Attempted to disconnect a functor from a signal it is not connected to.\n";
71 #endif
72}
73
74void signal_base::disconnect(const tacker* c)
75{
76 auto found = false;
77 receivers.erase(std::remove_if(receivers.begin(), receivers.end(), [this, &found, c](receiver& rcvr) {
78 if(rcvr.tacker_ptr == c) {
79 found = true;
80 unlink(rcvr);
81 return true;
82 }
83 return false;
84 }), receivers.end());
85
86 #ifndef NDEBUG
87 if (!found)
88 std::cerr << MSG_ERROR" Attempted to disconnect a tacker from a signal it is not connected to.\n";
89 #endif
90}
91
92void signal_base::disconnect_all()
93{
94 for (auto& rcvr : receivers)
95 unlink(rcvr);
96 receivers.clear();
97}
98
99
100const tacker* functor_base::get_tacker() const
101{
102 return dynamic_cast<const tacker*>(this);
103}
104
105bool functor_base::operator == (const functor_base& f) const
106{
107 const void *p1, *p2, *q1, *q2;
108 put_pointers(p1,p2);
109 f.put_pointers(q1,q2);
110 return p1 == q1 && p2 == q2;
111}
112
113
114void tacker::tack(signal_base* s) const
115{
116 ++signals[s];
117}
118void tacker::untack(signal_base* s) const
119{
120 const auto s_it = signals.find(s);
121 if (s_it == signals.end()) {
122 #ifndef NDEBUG
123 std::cout << MSG_ERROR" Attempted to untack a signal for a tacker that is not connected to it.\n";
124 #endif
125 return;
126 }
127
128 if (--s_it->second == 0)
129 signals.erase(s_it);
130}
131
132void tacker::untack_all() const
133{
134 for (auto& signal : signals) {
135 auto& receivers = signal.first->receivers;
136 int removed = 0;
137 bool done = false;
138 receivers.erase(std::remove_if(receivers.begin(), receivers.end(), [this, &signal, &done, &removed](signal_base::receiver& rcvr) {
139 if(!done && rcvr.tacker_ptr == this) {
140 if(++removed == signal.second)
141 done = true;
142 return true;
143 }
144 return false;
145 }), receivers.end());
146 }
147}
148
149tacker::~tacker() noexcept
150{
151 untack_all();
152}
153
154
155 }
156}
this header is dependency free
Definition print.h:11