cgv
Loading...
Searching...
No Matches
abst_signal.cxx
1#include <cgv/signal/abst_signal.h>
2#include "signal.h"
3
4namespace cgv {
5 namespace signal {
6
7void connect(signal<>& s, void(*fp)())
8{
9 s.connect(function_functor<0>(fp));
10}
11
12void disconnect(signal<>& s, void(*fp)())
13{
14 s.disconnect(function_functor<0>(fp));
15}
16
17signal_base::~signal_base()
18{
19 disconnect_all();
20}
21
23unsigned signal_base::get_nr_functors() const
24{
25 return (unsigned) functors.size();
26}
27
29void signal_base::connect_abst(functor_base* fp)
30{
31 connect(fp);
32}
33
34void signal_base::link(functor_base* fp)
35{
36 const tacker* t = fp->get_tacker();
37 if (t)
38 t->tack(this);
39}
40
41void signal_base::unlink(functor_base* fp)
42{
43 const tacker* t = fp->get_tacker();
44 if (t)
45 t->untack(this);
46 delete fp;
47}
48
49void signal_base::connect(functor_base* fp)
50{
51 link(fp);
52 functors.push_back(fp);
53}
54
55void signal_base::disconnect(const functor_base* fp)
56{
57 unsigned int i;
58 for (i=0; i<functors.size(); ++i) {
59 if (*functors[i] == *fp) {
60 unlink(functors[i]);
61 functors.erase(functors.begin()+i);
62 --i;
63 }
64 }
65}
66
67void signal_base::disconnect(const tacker* c)
68{
69 unsigned int i;
70 for (i=0; i<functors.size(); ++i) {
71 const auto tacker = functors[i]->get_tacker();
72 if (tacker == c) {
73 unlink(functors[i]);
74 functors.erase(functors.begin()+i);
75 --i;
76 }
77 }
78}
79
80
81void signal_base::disconnect_all()
82{
83 unsigned int i;
84 for (i=0; i<functors.size(); ++i)
85 unlink(functors[i]);
86 functors.clear();
87}
88
89functor_base::~functor_base()
90{
91}
92
93const tacker* functor_base::get_tacker() const
94{
95 return dynamic_cast<const tacker*>(this);
96}
97
98bool functor_base::operator == (const functor_base& f) const
99{
100 const void *p1, *p2, *q1, *q2;
101 put_pointers(p1,p2);
102 f.put_pointers(q1,q2);
103 return p1 == q1 && p2 == q2;
104}
105
106tacker::tacker()
107{
108}
109
111tacker::tacker(const tacker&)
112{
113}
114
115void tacker::tack(signal_base* s) const
116{
117 ++signals[s];
118}
119void tacker::untack(signal_base* s) const
120{
121 // some bug somewhere (probably in the stereo_view_interactor) causes internal state corruption
122 // to the "signals" container on non-Windows platforms, the non-Windows branch does some additional
123 // diagnostics (although the bug is not being worked around)
124 #ifdef _WIN32
125 if (--signals[s] <= 0)
126 signals.erase(signals.find(s));
127 #else
128 // TODO: signals.empty() and signals.size() return corrupted values after the stereo_view_interactor
129 // attempted to clean up its signals, necessitating a particularily nasty hack to work around
130 // a crash here
131 const auto sempty = signals.empty();
132 const auto ssize = signals.size();
133 constexpr std::size_t sanity_threshold = (unsigned short)-1;
134 if (sempty || ssize < 1 || ssize > sanity_threshold)
135 return;
136 const auto s_it = signals.find(s);
137 if (s_it != signals.end())
138 if (--(s_it->second) <= 0)
139 signals.erase(s_it);
140 #endif
141}
142
143void tacker::untack_all() const
144{
145 // some bug somewhere (probably in the stereo_view_interactor) causes
146 // this to be an infinite loop on non-Windows platforms
147 #ifdef _WIN32
148 while (!signals.empty())
149 signals.begin()->first->disconnect(this);
150 #else
151 // TODO: incredibly hacky workaraound, could break any time for any sort of non-trivial usage
152 // of signals - fix underling issue ASAP!
153 unsigned num_signals = signals.size();
154 while (!signals.empty()) {
155 signals.begin()->first->disconnect(this);
156 if (signals.size() >= num_signals)
157 // unregistering failed, break loop and leave all remaining registered
158 // objects in limbo
159 break;
160 num_signals = signals.size();
161 }
162 #endif
163}
164
165tacker::~tacker()
166{
167 untack_all();
168}
169
170
171 }
172}
the cgv namespace
Definition print.h:11