Fawkes API  Fawkes Development Version
interface_dispatcher.cpp
00001 
00002 /***************************************************************************
00003  *  interface_dispatcher.cpp - BlackBoard listener and dispatcher
00004  *
00005  *  Created: Thu Oct 09 23:07:16 2008
00006  *  Copyright  2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <gui_utils/interface_dispatcher.h>
00025 #include <interface/interface.h>
00026 
00027 namespace fawkes {
00028 
00029 /** @class InterfaceDispatcher <gui_utils/interface_dispatcher.h>
00030  * Interface listener with dispatcher.
00031  * An instance is used to react to a data changed event by triggering a
00032  * signal dispatcher (which is thread-safe and can be used across thread borders
00033  * in Glib/Gtk apps.
00034  * You have to register this listener with BlackBoard::BBIL_FLAGS_DATA flag by
00035  * yourself. Do not forget to unregister.
00036  * @author Tim Niemueller
00037  */
00038 
00039 /** Constructor.
00040  * @param listener_name name of the listener
00041  * @param iface interface to watch for data changes. Register this dispatcher as
00042  * listener by yourself!
00043  * @param message_enqueueing true to enqueue messages after the message received
00044  * event handler has been called, false to drop the message afterwards.
00045  */
00046 InterfaceDispatcher::InterfaceDispatcher(const char *listener_name,
00047                                          Interface *iface,
00048                                          bool message_enqueueing)
00049   : BlackBoardInterfaceListener(listener_name)
00050 {
00051   __message_enqueueing = message_enqueueing;
00052 
00053   bbil_add_data_interface(iface);
00054   if ( iface->is_writer() ) {
00055     bbil_add_message_interface(iface);
00056   }
00057   bbil_add_writer_interface(iface);
00058   bbil_add_reader_interface(iface);
00059 
00060   setup_signals();
00061 }
00062 
00063 /** Multi interface constructor.
00064  * @param listener_name name of the listener
00065  * @param ifaces list of interfaces to watch for data
00066  * changes. Register this dispatcher as listener by yourself!
00067  * @param message_enqueueing true to enqueue messages after the
00068  * message received event handler has been called, false to drop the
00069  * message afterwards.
00070  */
00071 InterfaceDispatcher::InterfaceDispatcher(const char *listener_name,
00072                                          std::list<Interface *> ifaces,
00073                                          bool message_enqueueing)
00074   : BlackBoardInterfaceListener(listener_name)
00075 {
00076   __message_enqueueing = message_enqueueing;
00077 
00078   std::list<Interface *>::iterator i;
00079   for (i = ifaces.begin(); i != ifaces.end(); ++i) {
00080     bbil_add_data_interface(*i);
00081     if ( (*i)->is_writer() ) {
00082       bbil_add_message_interface(*i);
00083     }
00084     bbil_add_writer_interface(*i);
00085     bbil_add_reader_interface(*i);
00086   }
00087 
00088   setup_signals();
00089 }
00090 
00091 
00092 void
00093 InterfaceDispatcher::setup_signals()
00094 {
00095   __dispatcher_data_changed.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_data_changed));
00096   __dispatcher_message_received.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_message_received));
00097   __dispatcher_writer_added.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_added));
00098   __dispatcher_writer_removed.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_removed));
00099   __dispatcher_reader_added.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_reader_added));
00100   __dispatcher_reader_removed.connect(sigc::mem_fun(*this, &InterfaceDispatcher::on_writer_removed));
00101 }
00102 
00103 /** Set if received messages should be enqueued or not.
00104  * The message received event handler can cause the message to be enqueued or not.
00105  * The default is to enqueue the messages.
00106  * @param enqueue true to cause messages to be enqueued, false to cause the
00107  * messages not to be enqueued after they have been processed
00108  */
00109 void
00110 InterfaceDispatcher::set_message_enqueueing(bool enqueue)
00111 {
00112   __message_enqueueing = enqueue;
00113 }
00114 
00115 
00116 /** Internal event handler.
00117  * Called by dispatcher to emit signal.
00118  */
00119 void
00120 InterfaceDispatcher::on_data_changed()
00121 {
00122   __queue_data_changed.lock();
00123   while (! __queue_data_changed.empty()) {
00124     Interface *iface = __queue_data_changed.front();
00125     __signal_data_changed.emit(iface);
00126     __queue_data_changed.pop();
00127   }
00128   __queue_data_changed.unlock();
00129 }
00130 
00131 
00132 /** Internal event handler.
00133  * Called by dispatcher to emit signal.
00134  */
00135 void
00136 InterfaceDispatcher::on_message_received()
00137 {
00138   __queue_message_received.lock();
00139   while (! __queue_message_received.empty()) {
00140     std::pair<Interface *, Message *> p = __queue_message_received.front();
00141     __signal_message_received.emit(p.first, p.second);
00142     p.second->unref();
00143     __queue_message_received.pop();
00144   }
00145   __queue_message_received.unlock();
00146 }
00147 
00148 
00149 /** Internal event handler.
00150  * Called by dispatcher to emit signal.
00151  */
00152 void
00153 InterfaceDispatcher::on_writer_added()
00154 {
00155   __queue_writer_added.lock();
00156   while (! __queue_writer_added.empty()) {
00157     Interface *iface = __queue_writer_added.front();
00158     __signal_writer_added.emit(iface);
00159     __queue_writer_added.pop();
00160   }
00161   __queue_writer_added.unlock();
00162 }
00163 
00164 
00165 /** Internal event handler.
00166  * Called by dispatcher to emit signal.
00167  */
00168 void
00169 InterfaceDispatcher::on_writer_removed()
00170 {
00171   __queue_writer_removed.lock();
00172   while (! __queue_writer_removed.empty()) {
00173     Interface *iface = __queue_writer_removed.front();
00174     __signal_writer_removed.emit(iface);
00175     __queue_writer_removed.pop();
00176   }
00177   __queue_writer_removed.unlock();
00178 }
00179 
00180 
00181 /** Internal event handler.
00182  * Called by dispatcher to emit signal.
00183  */
00184 void
00185 InterfaceDispatcher::on_reader_added()
00186 {
00187   __queue_reader_added.lock();
00188   while (! __queue_reader_added.empty()) {
00189     Interface *iface = __queue_reader_added.front();
00190     __signal_reader_added.emit(iface);
00191     __queue_reader_added.pop();
00192   }
00193   __queue_reader_added.unlock();
00194 }
00195 
00196 
00197 /** Internal event handler.
00198  * Called by dispatcher to emit signal.
00199  */
00200 void
00201 InterfaceDispatcher::on_reader_removed()
00202 {
00203   __queue_reader_removed.lock();
00204   while (! __queue_reader_removed.empty()) {
00205     Interface *iface = __queue_reader_removed.front();
00206     __signal_reader_removed.emit(iface);
00207     __queue_reader_removed.pop();
00208   }
00209   __queue_reader_removed.unlock();
00210 }
00211 
00212 
00213 void
00214 InterfaceDispatcher::bb_interface_data_changed(Interface *interface) throw()
00215 {
00216   __queue_data_changed.push_locked(interface);
00217   __dispatcher_data_changed();
00218 }
00219 
00220 bool
00221 InterfaceDispatcher::bb_interface_message_received(Interface *interface, Message *message) throw()
00222 {
00223   message->ref();
00224   __queue_message_received.push_locked(std::make_pair(interface, message));
00225   __dispatcher_message_received();
00226   return __message_enqueueing;
00227 }
00228 
00229 void
00230 InterfaceDispatcher::bb_interface_writer_added(Interface *interface,
00231                                                unsigned int instance_serial) throw()
00232 {
00233   __queue_writer_added.push_locked(interface);
00234   __dispatcher_writer_added();
00235 }
00236 
00237 void
00238 InterfaceDispatcher::bb_interface_writer_removed(Interface *interface,
00239                                                  unsigned int instance_serial) throw()
00240 {
00241   __queue_writer_removed.push_locked(interface);
00242   __dispatcher_writer_removed();
00243 }
00244 
00245 void
00246 InterfaceDispatcher::bb_interface_reader_added(Interface *interface,
00247                                                unsigned int instance_serial) throw()
00248 {
00249   __queue_reader_added.push_locked(interface);
00250   __dispatcher_reader_added();
00251 }
00252 
00253 void
00254 InterfaceDispatcher::bb_interface_reader_removed(Interface *interface,
00255                                                  unsigned int instance_serial) throw()
00256 {
00257   __queue_reader_removed.push_locked(interface);
00258   __dispatcher_reader_removed();
00259 }
00260 
00261 /** Get "data changed" signal.
00262  * The signal is emitted if the data of the interface has changed.
00263  * @return "data changed" signal.
00264  */
00265 sigc::signal<void, Interface *>
00266 InterfaceDispatcher::signal_data_changed()
00267 {
00268   return __signal_data_changed;
00269 }
00270 
00271 
00272 /** Get "message received" signal.
00273  * The signal is emitted if a message has been received via the watched
00274  * interface. Note that this signal is only emitted on writing instances of
00275  * an interface.
00276  * @return "message received" signal.
00277  */
00278 sigc::signal<void, Interface *, Message *>
00279 InterfaceDispatcher::signal_message_received()
00280 {
00281   return __signal_message_received;
00282 }
00283 
00284 
00285 /** Get "writer added" signal.
00286  * The signal is emitted if a writer has been added to the interface.
00287  * @return "writer added" signal.
00288  */
00289 sigc::signal<void, Interface *>
00290 InterfaceDispatcher::signal_writer_added()
00291 {
00292   return __signal_writer_added;
00293 }
00294 
00295 
00296 /** Get "writer removed" signal.
00297  * The signal is emitted if a writer has been removed from the interface.
00298  * @return "writer removed" signal.
00299  */
00300 sigc::signal<void, Interface *>
00301 InterfaceDispatcher::signal_writer_removed()
00302 {
00303   return __signal_writer_removed;
00304 }
00305 
00306 
00307 /** Get "reader added" signal.
00308  * The signal is emitted if a reader has been added to the interface.
00309  * @return "reader added" signal.
00310  */
00311 sigc::signal<void, Interface *>
00312 InterfaceDispatcher::signal_reader_added()
00313 {
00314   return __signal_reader_added;
00315 }
00316 
00317 
00318 /** Get "reader removed" signal.
00319  * The signal is emitted if a reader has been removed from the interface.
00320  * @return "reader added" signal.
00321  */
00322 sigc::signal<void, Interface *>
00323 InterfaceDispatcher::signal_reader_removed()
00324 {
00325   return __signal_reader_removed;
00326 }
00327 
00328 
00329 } // end of namespace fawkes