Fawkes API  Fawkes Development Version
interface_dispatcher.cpp
1 
2 /***************************************************************************
3  * interface_dispatcher.cpp - BlackBoard listener and dispatcher
4  *
5  * Created: Thu Oct 09 23:07:16 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <gui_utils/interface_dispatcher.h>
25 #include <interface/interface.h>
26 
27 namespace fawkes {
28 
29 /** @class InterfaceDispatcher <gui_utils/interface_dispatcher.h>
30  * Interface listener with dispatcher.
31  * An instance is used to react to a data changed event by triggering a
32  * signal dispatcher (which is thread-safe and can be used across thread borders
33  * in Glib/Gtk apps.
34  * You have to register this listener with BlackBoard::BBIL_FLAGS_DATA flag by
35  * yourself. Do not forget to unregister.
36  * @author Tim Niemueller
37  */
38 
39 /** Constructor.
40  * @param listener_name name of the listener
41  * @param iface interface to watch for data changes. Register this dispatcher as
42  * listener by yourself!
43  * @param message_enqueueing true to enqueue messages after the message received
44  * event handler has been called, false to drop the message afterwards.
45  */
46 InterfaceDispatcher::InterfaceDispatcher(const char *listener_name,
47  Interface * iface,
48  bool message_enqueueing)
49 : BlackBoardInterfaceListener(listener_name)
50 {
51  message_enqueueing_ = message_enqueueing;
52 
54  if (iface->is_writer()) {
56  }
59 
60  setup_signals();
61 }
62 
63 /** Multi interface constructor.
64  * @param listener_name name of the listener
65  * @param ifaces list of interfaces to watch for data
66  * changes. Register this dispatcher as listener by yourself!
67  * @param message_enqueueing true to enqueue messages after the
68  * message received event handler has been called, false to drop the
69  * message afterwards.
70  */
71 InterfaceDispatcher::InterfaceDispatcher(const char * listener_name,
72  std::list<Interface *> ifaces,
73  bool message_enqueueing)
74 : BlackBoardInterfaceListener(listener_name)
75 {
76  message_enqueueing_ = message_enqueueing;
77 
78  std::list<Interface *>::iterator i;
79  for (i = ifaces.begin(); i != ifaces.end(); ++i) {
81  if ((*i)->is_writer()) {
83  }
86  }
87 
88  setup_signals();
89 }
90 
91 void
92 InterfaceDispatcher::setup_signals()
93 {
94  dispatcher_data_changed_.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_data_changed));
95  dispatcher_message_received_.connect(
96  sigc::mem_fun(*this, &InterfaceDispatcher::on_message_received));
97  dispatcher_writer_added_.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_added));
98  dispatcher_writer_removed_.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_removed));
99  dispatcher_reader_added_.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_reader_added));
100  dispatcher_reader_removed_.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_removed));
101 }
102 
103 /** Set if received messages should be enqueued or not.
104  * The message received event handler can cause the message to be enqueued or not.
105  * The default is to enqueue the messages.
106  * @param enqueue true to cause messages to be enqueued, false to cause the
107  * messages not to be enqueued after they have been processed
108  */
109 void
111 {
112  message_enqueueing_ = enqueue;
113 }
114 
115 /** Internal event handler.
116  * Called by dispatcher to emit signal.
117  */
118 void
120 {
121  queue_data_changed_.lock();
122  while (!queue_data_changed_.empty()) {
123  Interface *iface = queue_data_changed_.front();
124  signal_data_changed_.emit(iface);
125  queue_data_changed_.pop();
126  }
127  queue_data_changed_.unlock();
128 }
129 
130 /** Internal event handler.
131  * Called by dispatcher to emit signal.
132  */
133 void
135 {
136  queue_message_received_.lock();
137  while (!queue_message_received_.empty()) {
138  std::pair<Interface *, Message *> p = queue_message_received_.front();
139  signal_message_received_.emit(p.first, p.second);
140  p.second->unref();
141  queue_message_received_.pop();
142  }
143  queue_message_received_.unlock();
144 }
145 
146 /** Internal event handler.
147  * Called by dispatcher to emit signal.
148  */
149 void
151 {
152  queue_writer_added_.lock();
153  while (!queue_writer_added_.empty()) {
154  Interface *iface = queue_writer_added_.front();
155  signal_writer_added_.emit(iface);
156  queue_writer_added_.pop();
157  }
158  queue_writer_added_.unlock();
159 }
160 
161 /** Internal event handler.
162  * Called by dispatcher to emit signal.
163  */
164 void
166 {
167  queue_writer_removed_.lock();
168  while (!queue_writer_removed_.empty()) {
169  Interface *iface = queue_writer_removed_.front();
170  signal_writer_removed_.emit(iface);
171  queue_writer_removed_.pop();
172  }
173  queue_writer_removed_.unlock();
174 }
175 
176 /** Internal event handler.
177  * Called by dispatcher to emit signal.
178  */
179 void
181 {
182  queue_reader_added_.lock();
183  while (!queue_reader_added_.empty()) {
184  Interface *iface = queue_reader_added_.front();
185  signal_reader_added_.emit(iface);
186  queue_reader_added_.pop();
187  }
188  queue_reader_added_.unlock();
189 }
190 
191 /** Internal event handler.
192  * Called by dispatcher to emit signal.
193  */
194 void
196 {
197  queue_reader_removed_.lock();
198  while (!queue_reader_removed_.empty()) {
199  Interface *iface = queue_reader_removed_.front();
200  signal_reader_removed_.emit(iface);
201  queue_reader_removed_.pop();
202  }
203  queue_reader_removed_.unlock();
204 }
205 
206 void
208 {
209  queue_data_changed_.push_locked(interface);
210  dispatcher_data_changed_();
211 }
212 
213 bool
215 {
216  message->ref();
217  queue_message_received_.push_locked(std::make_pair(interface, message));
218  dispatcher_message_received_();
219  return message_enqueueing_;
220 }
221 
222 void
223 InterfaceDispatcher::bb_interface_writer_added(Interface *interface, Uuid instance_serial) noexcept
224 {
225  queue_writer_added_.push_locked(interface);
226  dispatcher_writer_added_();
227 }
228 
229 void
231  Uuid instance_serial) noexcept
232 {
233  queue_writer_removed_.push_locked(interface);
234  dispatcher_writer_removed_();
235 }
236 
237 void
238 InterfaceDispatcher::bb_interface_reader_added(Interface *interface, Uuid instance_serial) noexcept
239 {
240  queue_reader_added_.push_locked(interface);
241  dispatcher_reader_added_();
242 }
243 
244 void
246  Uuid instance_serial) noexcept
247 {
248  queue_reader_removed_.push_locked(interface);
249  dispatcher_reader_removed_();
250 }
251 
252 /** Get "data changed" signal.
253  * The signal is emitted if the data of the interface has changed.
254  * @return "data changed" signal.
255  */
256 sigc::signal<void, Interface *>
258 {
259  return signal_data_changed_;
260 }
261 
262 /** Get "message received" signal.
263  * The signal is emitted if a message has been received via the watched
264  * interface. Note that this signal is only emitted on writing instances of
265  * an interface.
266  * @return "message received" signal.
267  */
268 sigc::signal<void, Interface *, Message *>
270 {
271  return signal_message_received_;
272 }
273 
274 /** Get "writer added" signal.
275  * The signal is emitted if a writer has been added to the interface.
276  * @return "writer added" signal.
277  */
278 sigc::signal<void, Interface *>
280 {
281  return signal_writer_added_;
282 }
283 
284 /** Get "writer removed" signal.
285  * The signal is emitted if a writer has been removed from the interface.
286  * @return "writer removed" signal.
287  */
288 sigc::signal<void, Interface *>
290 {
291  return signal_writer_removed_;
292 }
293 
294 /** Get "reader added" signal.
295  * The signal is emitted if a reader has been added to the interface.
296  * @return "reader added" signal.
297  */
298 sigc::signal<void, Interface *>
300 {
301  return signal_reader_added_;
302 }
303 
304 /** Get "reader removed" signal.
305  * The signal is emitted if a reader has been removed from the interface.
306  * @return "reader added" signal.
307  */
308 sigc::signal<void, Interface *>
310 {
311  return signal_reader_removed_;
312 }
313 
314 } // end of namespace fawkes
BlackBoard interface listener.
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
void bbil_add_message_interface(Interface *interface)
Add an interface to the message received watch list.
void bbil_add_writer_interface(Interface *interface)
Add an interface to the writer addition/removal watch list.
void bbil_add_data_interface(Interface *interface)
Add an interface to the data modification watch list.
sigc::signal< void, Interface *, Message * > signal_message_received()
Get "message received" signal.
sigc::signal< void, Interface * > signal_reader_added()
Get "reader added" signal.
sigc::signal< void, Interface * > signal_reader_removed()
Get "reader removed" signal.
virtual void bb_interface_reader_added(Interface *interface, Uuid instance_serial) noexcept
A reading instance has been opened for a watched interface.
virtual void on_writer_added()
Internal event handler.
void set_message_enqueueing(bool enqueue)
Set if received messages should be enqueued or not.
sigc::signal< void, Interface * > signal_writer_added()
Get "writer added" signal.
virtual void on_data_changed()
Internal event handler.
virtual bool bb_interface_message_received(Interface *interface, Message *message) noexcept
BlackBoard message received notification.
virtual void on_reader_added()
Internal event handler.
virtual void bb_interface_reader_removed(Interface *interface, Uuid instance_serial) noexcept
A reading instance has been closed for a watched interface.
virtual void bb_interface_data_refreshed(Interface *interface) noexcept
BlackBoard data refreshed notification.
virtual void bb_interface_writer_added(Interface *interface, Uuid instance_serial) noexcept
A writing instance has been opened for a watched interface.
virtual void bb_interface_writer_removed(Interface *interface, Uuid instance_serial) noexcept
A writing instance has been closed for a watched interface.
sigc::signal< void, Interface * > signal_writer_removed()
Get "writer removed" signal.
virtual void on_message_received()
Internal event handler.
sigc::signal< void, Interface * > signal_data_changed()
Get "data changed" signal.
virtual void on_writer_removed()
Internal event handler.
virtual void on_reader_removed()
Internal event handler.
InterfaceDispatcher(const char *listener_name, fawkes::Interface *iface, bool message_enqueueing=true)
Constructor.
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
bool is_writer() const
Check if this is a writing instance.
Definition: interface.cpp:445
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
A convenience class for universally unique identifiers (UUIDs).
Definition: uuid.h:29
Fawkes library namespace.