comparison anagram/support/agsignal.h @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 /*
2 * AnaGram, A System for Syntax Directed Programming
3 * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
4 * See the file COPYING for license and usage terms.
5 *
6 * agsignal.h
7 */
8
9 #ifndef AGSIGNAL_H
10 #define AGSIGNAL_H
11
12 #include "agstack.h"
13 #include "assert.h"
14
15 /*
16 * The classes Broadcaster<Message> and Requester<Message> allow type-safe
17 * run-time binding to class methods where the name of the class containing
18 * the method being called is not known to the calling method.
19 *
20 * Any method m with the prototype
21 * void f(const Message &);
22 * belonging to an instance x of class X can by bound to a Broadcaster<Message>
23 * instance b in an instance y of a class Y by the following call:
24 * connect(&x, X::f, y.b);
25 *
26 * Any number of "listeners" may be attached to a given broadcaster.
27 *
28 * For each type of message that an object is to send, it must have a member
29 * object either of type Broadcaster<Message> or Requester<Message>, where
30 * Message is an arbitrary class.
31 *
32 * If an instance x of the class X has a member b of type Broadcaster<Message>
33 * a handler function h(const Message &) belonging to an instance, y, of an
34 * arbitrary class Y may be connected to the
35 *
36 * [...? the comment stopped here]
37 */
38
39 template <class Signal>
40 class Listener {
41 public:
42 Listener() {}
43 Listener(const Listener<Signal> &) {}
44 virtual ~Listener() {}
45 virtual void handle(const Signal &) { assert(0); }
46 virtual int operator == (const Listener<Signal> &p) const {
47 return p == *this;
48 }
49 virtual int operator < (const Listener<Signal> &) const { return 0; }
50 //virtual Listener<Signal> *copy() const {
51 // assert(0);
52 // return (Listener<Signal> *)this;
53 //}
54 virtual Listener<Signal> *copy() const { assert(0); return NULL; }
55 };
56
57 template <class Signal>
58 class Broadcaster {
59 private:
60 AgStack<Listener<Signal> *> listenerStack;
61 protected:
62 void broadcast(const Signal &) const;
63 public:
64 Broadcaster(int log = 3) : listenerStack(log) {}
65 void add(const Listener<Signal> &);
66 void remove(const Listener<Signal> &);
67 };
68
69 template <class Host, class Signal>
70 class ListenerFor : public Listener<Signal> {
71 private:
72 Host *host;
73 void (Host::*handler)(const Signal &);
74 public:
75 ListenerFor(Host *t, void (Host::*h)(const Signal &))
76 : host(t), handler(h) {}
77 ListenerFor(const ListenerFor<Host, Signal> &x)
78 : host(x.host), handler(x.handler) {}
79 void handle(const Signal &s) { (host->*handler)(s); }
80 int operator == (const Listener<Signal> &r) const {
81 const ListenerFor<Host,Signal> &rf = (const ListenerFor<Host,Signal> &) r;
82 return (host == rf.host && handler == rf.handler);
83 }
84 int operator < (const Listener<Signal> &r) const {
85 const ListenerFor<Host,Signal> &rf = (const ListenerFor<Host,Signal> &) r;
86 return host == rf.host ? &handler < &rf.handler : host < rf.host;
87 }
88 ListenerFor<Host,Signal> *copy() const {
89 return new ListenerFor<Host,Signal>(host, handler);
90 }
91 };
92
93 template <class Signal>
94 void Broadcaster<Signal>::add(const Listener<Signal> &s) {
95 int n = listenerStack.size();
96 int i;
97 for (i = 0; i < n; i++) {
98 if (s == *listenerStack[i]) {
99 return;
100 }
101 }
102 listenerStack.push(s.copy());
103 }
104
105 template <class Signal>
106 void Broadcaster<Signal>::remove(const Listener<Signal> &s) {
107 int n = listenerStack.size();
108 int i;
109 for (i = 0; i < n; i++) {
110 if (s == *listenerStack[i]) {
111 break;
112 }
113 }
114 if (i == n) {
115 return;
116 }
117 delete listenerStack[i];
118 while (++i < n) {
119 listenerStack[i-1] = listenerStack[i];
120 }
121 listenerStack.pop();
122 }
123
124 template <class Signal>
125 void Broadcaster<Signal>::broadcast(const Signal &s) const {
126 int n = listenerStack.size();
127 int i;
128 for (i = 0; i < n; i++) {
129 listenerStack[i]->handle(s);
130 }
131 }
132
133 template <class Host, class Signal>
134 void connect(Host *host, void (Host::*handler)(const Signal &),
135 Broadcaster<Signal> &broadcaster) {
136 broadcaster.add(ListenerFor<Host,Signal>(host, handler));
137 }
138
139 template <class Host, class Signal>
140 void disconnect(Host *host, void (Host::*handler)(const Signal &),
141 Broadcaster<Signal> &broadcaster) {
142 broadcaster.remove(ListenerFor<Host,Signal>(host, handler));
143 }
144
145 template <class Signal>
146 class Responder {
147 public:
148 virtual void handle(Signal &) = 0;
149 virtual int operator == (const Responder<Signal> &p) const = 0;
150 virtual int operator == (const Responder<Signal> *p) const {
151 return *p == *this;
152 }
153 virtual Responder<Signal> *copy() const = 0;
154 };
155
156 template <class Signal>
157 class Requester {
158 private:
159 AgStack<Responder<Signal> *> responderStack;
160 int level;
161
162 protected:
163 void request(Signal &);
164
165 public:
166 Requester() : responderStack(3), level(0) {}
167 void add(const Responder<Signal> &r) {
168 responderStack.push(r.copy());
169 level++;
170 }
171 void add(Responder<Signal> *r) {
172 responderStack.push(r);
173 level++;
174 }
175 void remove(const Responder<Signal> &);
176 Responder<Signal> *pop() { return responderStack.pop(); }
177 };
178
179 template <class Host, class Signal>
180 class ResponderFor : public Responder<Signal> {
181 private:
182 Host *host;
183 void (Host::*handler)(Signal &);
184
185 public:
186 ResponderFor(Host *t, void (Host::*h)(Signal &)) : host(t), handler(h) {}
187 void handle(Signal &s) { (host->*handler)(s); }
188 int operator == (const Responder<Signal> &r) const {
189 const ResponderFor<Host,Signal> &rf =
190 (const ResponderFor<Host,Signal> &) r;
191 return (host == rf.host && handler == rf.handler);
192 }
193 Responder<Signal> *copy() const {
194 return new ResponderFor<Host,Signal>(host, handler);
195 }
196 };
197
198 template <class Signal>
199 void Requester<Signal>::remove(const Responder<Signal> &s) {
200 int n = responderStack.size();
201 int i;
202 for (i = 0; i < n; i++) {
203 if (s == responderStack[i]) {
204 break;
205 }
206 }
207 if (i == n) {
208 return;
209 }
210 delete responderStack[i];
211 if (level >= i) {
212 level--;
213 }
214 while (++i < n) {
215 responderStack[i-1] = responderStack[i];
216 }
217 responderStack.pop();
218 }
219
220 template <class Signal>
221 void Requester<Signal>::request(Signal &s) {
222 assert(level > 0);
223 level--;
224 responderStack[level]->handle(s);
225 level++;
226 }
227
228 template <class Host, class Signal>
229 void connect(Host *host, void (Host::*handler)(Signal &),
230 Requester<Signal> &requester) {
231 requester.add(ResponderFor<Host,Signal>(host, handler));
232 }
233
234 template <class Host, class Signal>
235 void disconnect(Host *host, void (Host::*handler)(Signal &),
236 Requester<Signal> &requester) {
237 requester.add(ResponderFor<Host,Signal>(host, handler));
238 }
239
240 template <class Signal>
241 void reroute(Requester<Signal> &from, Requester<Signal> &to) {
242 to.add(from.pop());
243 }
244
245
246 #endif /* AGSIGNAL_H */