Fawkes API
Fawkes Development Version
|
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