Fawkes API  Fawkes Development Version
notifier.cpp
1 
2 /***************************************************************************
3  * notifier.cpp - BlackBoard notifier
4  *
5  * Created: Mon Mar 03 23:28:18 2008
6  * Copyright 2006-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 <blackboard/internal/notifier.h>
25 #include <blackboard/blackboard.h>
26 #include <blackboard/interface_listener.h>
27 #include <blackboard/interface_observer.h>
28 
29 #include <core/threading/mutex.h>
30 #include <core/threading/mutex_locker.h>
31 #include <core/utils/lock_hashset.h>
32 #include <core/utils/lock_hashmap.h>
33 #include <logging/liblogger.h>
34 #include <interface/interface.h>
35 
36 #include <algorithm>
37 #include <functional>
38 #include <cstdlib>
39 #include <cstring>
40 #include <fnmatch.h>
41 
42 namespace fawkes {
43 
44 /** @class BlackBoardNotifier <blackboard/internal/notifier.h>
45  * BlackBoard notifier.
46  * This class is used by the BlackBoard to notify listeners and observers
47  * of changes.
48  *
49  * @author Tim Niemueller
50  */
51 
52 
53 /** Constructor. */
55 {
56  __bbil_writer_events = 0;
57  __bbil_writer_mutex = new Mutex();
58 
59  __bbil_reader_events = 0;
60  __bbil_reader_mutex = new Mutex();
61 
62  __bbil_data_events = 0;
63  __bbil_data_mutex = new Mutex();
64 
65  __bbil_messages_events = 0;
66  __bbil_messages_mutex = new Mutex();
67 
68  __bbio_events = 0;
69  __bbio_mutex = new Mutex();
70 }
71 
72 
73 /** Destructor */
75 {
76  delete __bbil_writer_mutex;
77  delete __bbil_reader_mutex;
78  delete __bbil_data_mutex;
79  delete __bbil_messages_mutex;
80 
81  delete __bbio_mutex;
82 }
83 
84 /** Register BB event listener.
85  * @param listener BlackBoard event listener to register
86  * @param flag concatenation of flags denoting which queue entries should be
87  * processed
88  */
89 void
92 {
93  update_listener(listener, flag);
94 }
95 
96 
97 /** Update BB event listener.
98  * @param listener BlackBoard event listener to update subscriptions of
99  * @param flag concatenation of flags denoting which queue entries should be
100  * processed
101  */
102 void
105 {
107  listener->bbil_acquire_queue();
108 
109  BlackBoardInterfaceListener::InterfaceQueue::const_iterator i = queue.begin();
110 
111  for (i = queue.begin(); i != queue.end(); ++i) {
112  switch (i->type) {
114  if (flag & BlackBoard::BBIL_FLAG_DATA) {
115  proc_listener_maybe_queue(i->op, i->interface, listener,
116  __bbil_data_mutex, __bbil_data_events,
117  __bbil_data, __bbil_data_queue, "data");
118  }
119  break;
121  if (flag & BlackBoard::BBIL_FLAG_MESSAGES) {
122  proc_listener_maybe_queue(i->op, i->interface, listener,
123  __bbil_messages_mutex, __bbil_messages_events,
124  __bbil_messages, __bbil_messages_queue,
125  "messages");
126  }
127  break;
129  if (flag & BlackBoard::BBIL_FLAG_READER) {
130  proc_listener_maybe_queue(i->op, i->interface, listener,
131  __bbil_reader_mutex, __bbil_reader_events,
132  __bbil_reader, __bbil_reader_queue, "reader");
133  }
134  break;
136  if (flag & BlackBoard::BBIL_FLAG_WRITER) {
137  proc_listener_maybe_queue(i->op, i->interface, listener,
138  __bbil_writer_mutex, __bbil_writer_events,
139  __bbil_writer, __bbil_writer_queue, "writer");
140  }
141  break;
142  default: break;
143  }
144  }
145 
146  listener->bbil_release_queue(flag);
147 }
148 
149 void
150 BlackBoardNotifier::proc_listener_maybe_queue(bool op,
151  Interface *interface,
152  BlackBoardInterfaceListener *listener,
153  Mutex *mutex, unsigned int &events,
154  BBilMap &map, BBilQueue &queue,
155  const char *hint)
156 {
157  MutexLocker lock(mutex);
158  if (events > 0) {
159  LibLogger::log_warn("BlackBoardNotifier", "Registering interface "
160  "listener %s for %s events (queued)",
161  listener->bbil_name(), hint);
162 
163  queue_listener(op, interface, listener, queue);
164  } else {
165  if (op) { // add
166  add_listener(interface, listener, map);
167  } else {
168  remove_listener(interface, listener, map);
169  }
170  }
171 }
172 
173 
174 /** Unregister BB interface listener.
175  * This will remove the given BlackBoard interface listener from any
176  * event that it was previously registered for.
177  * @param listener BlackBoard event listener to remove
178  */
179 void
181 {
183  listener->bbil_acquire_maps();
184 
185  BlackBoardInterfaceListener::InterfaceMap::const_iterator i;
186  for (i = maps.data.begin(); i != maps.data.end(); ++i) {
187  proc_listener_maybe_queue(false, i->second, listener,
188  __bbil_data_mutex, __bbil_data_events,
189  __bbil_data, __bbil_data_queue, "data");
190  }
191 
192  for (i = maps.messages.begin(); i != maps.messages.end(); ++i) {
193  proc_listener_maybe_queue(false, i->second, listener,
194  __bbil_messages_mutex, __bbil_messages_events,
195  __bbil_messages, __bbil_messages_queue,
196  "messages");
197  }
198 
199  for (i = maps.reader.begin(); i != maps.reader.end(); ++i) {
200  proc_listener_maybe_queue(false, i->second, listener,
201  __bbil_reader_mutex, __bbil_reader_events,
202  __bbil_reader, __bbil_reader_queue, "reader");
203  }
204 
205  for (i = maps.writer.begin(); i != maps.writer.end(); ++i) {
206  proc_listener_maybe_queue(false, i->second, listener,
207  __bbil_writer_mutex, __bbil_writer_events,
208  __bbil_writer, __bbil_writer_queue, "writer");
209  }
210 
211  listener->bbil_release_maps();
212 }
213 
214 /** Add listener for specified map.
215  * @param listener interface listener for events
216  * @param im map of interfaces to listen for
217  * @param ilmap internal map to add listener to
218  */
219 void
220 BlackBoardNotifier::add_listener(Interface *interface,
221  BlackBoardInterfaceListener *listener,
222  BBilMap &ilmap)
223 {
224  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
225  ilmap.equal_range(interface->uid());
226 
227  BBilMap::value_type v = std::make_pair(interface->uid(), listener);
228  BBilMap::iterator f = std::find(ret.first, ret.second, v);
229 
230  if (f == ret.second) {
231  ilmap.insert(std::make_pair(interface->uid(), listener));
232  }
233 }
234 
235 void
236 BlackBoardNotifier::remove_listener(Interface *interface,
237  BlackBoardInterfaceListener *listener,
238  BBilMap &ilmap)
239 {
240  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
241  ilmap.equal_range(interface->uid());
242  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
243  if (j->second == listener) {
244  ilmap.erase(j);
245  break;
246  }
247  }
248 }
249 
250 
251 bool
252 BlackBoardNotifier::is_in_queue(bool op, BBilQueue &queue, const char *uid,
254 {
255  BBilQueue::iterator q;
256  for (q = queue.begin(); q != queue.end(); ++q) {
257  if ((q->op == op) && (q->uid == uid) && (q->listener == bbil)) {
258  return true;
259  }
260  }
261  return false;
262 }
263 
264 void
265 BlackBoardNotifier::queue_listener(bool op, Interface *interface,
266  BlackBoardInterfaceListener *listener,
267  BBilQueue &queue)
268 {
269  BBilQueueEntry qe = { op, interface->uid(), interface, listener };
270  queue.push_back(qe);
271 }
272 
273 
274 
275 /** Register BB interface observer.
276  * @param observer BlackBoard interface observer to register
277  */
278 void
280 {
281  __bbio_mutex->lock();
282  if (__bbio_events > 0) {
283  __bbio_queue.push_back(std::make_pair(1, observer));
284  } else {
285  add_observer(observer, observer->bbio_get_observed_create(), __bbio_created);
286  add_observer(observer, observer->bbio_get_observed_destroy(), __bbio_destroyed);
287  }
288  __bbio_mutex->unlock();
289 }
290 
291 
292 void
293 BlackBoardNotifier::add_observer(BlackBoardInterfaceObserver *observer,
295  BBioMap &bbiomap)
296 {
298  its->lock();
299  for (i = its->begin(); i != its->end(); ++i) {
300  bbiomap[i->first].push_back(make_pair(observer, i->second));
301  }
302  its->unlock();
303 }
304 
305 
306 /** Remove observer from map.
307  * @param iomap interface observer map to remove the observer from
308  * @param observer observer to remove
309  */
310 void
311 BlackBoardNotifier::remove_observer(BBioMap &iomap, BlackBoardInterfaceObserver *observer)
312 {
313  BBioMapIterator i, tmp;
314 
315  i = iomap.begin();
316  while (i != iomap.end()) {
317  BBioListIterator j = i->second.begin();
318  while (j != i->second.end()) {
319  if ( j->first == observer ) {
320  j = i->second.erase(j);
321  } else {
322  ++j;
323  }
324  }
325  if ( i->second.empty() ) {
326  tmp = i;
327  ++i;
328  iomap.erase(tmp);
329  } else {
330  ++i;
331  }
332  }
333 }
334 
335 /** Unregister BB interface observer.
336  * This will remove the given BlackBoard event listener from any event that it was
337  * previously registered for.
338  * @param observer BlackBoard event listener to remove
339  */
340 void
342 {
343  MutexLocker lock(__bbio_mutex);
344  if ( __bbio_events > 0) {
345  BBioQueueEntry e = std::make_pair((unsigned int)0, observer);
346  BBioQueue::iterator re;
347  while ( (re = find_if(__bbio_queue.begin(), __bbio_queue.end(),
348  bind2nd(std::not_equal_to<BBioQueueEntry>(), e)))
349  != __bbio_queue.end()) {
350  // if there is an entry in the register queue, remove it!
351  if (re->second == observer) {
352  __bbio_queue.erase(re);
353  }
354  }
355  __bbio_queue.push_back(std::make_pair(0, observer));
356 
357  } else {
358  remove_observer(__bbio_created, observer);
359  remove_observer(__bbio_destroyed, observer);
360  }
361 }
362 
363 /** Notify that an interface has been created.
364  * @param type type of the interface
365  * @param id ID of the interface
366  */
367 void
368 BlackBoardNotifier::notify_of_interface_created(const char *type, const char *id) throw()
369 {
370  __bbio_mutex->lock();
371  __bbio_events += 1;
372  __bbio_mutex->unlock();
373 
374  BBioMapIterator lhmi;
375  BBioListIterator i, l;
376  for (lhmi = __bbio_created.begin(); lhmi != __bbio_created.end(); ++lhmi) {
377  if (fnmatch(lhmi->first.c_str(), type, 0) != 0) continue;
378 
379  BBioList &list = lhmi->second;
380  for (i = list.begin(); i != list.end(); ++i) {
381  BlackBoardInterfaceObserver *bbio = i->first;
382  for (std::list<std::string>::iterator pi = i->second.begin(); pi != i->second.end(); ++pi) {
383  if (fnmatch(pi->c_str(), id, 0) == 0) {
384  bbio->bb_interface_created(type, id);
385  break;
386  }
387  }
388  }
389  }
390 
391  __bbio_mutex->lock();
392  __bbio_events -= 1;
393  process_bbio_queue();
394  __bbio_mutex->unlock();
395 }
396 
397 
398 /** Notify that an interface has been destroyed.
399  * @param type type of the interface
400  * @param id ID of the interface
401  */
402 void
403 BlackBoardNotifier::notify_of_interface_destroyed(const char *type, const char *id) throw()
404 {
405  __bbio_mutex->lock();
406  __bbio_events += 1;
407  __bbio_mutex->unlock();
408 
409  BBioMapIterator lhmi;
410  BBioListIterator i, l;
411  for (lhmi = __bbio_destroyed.begin(); lhmi != __bbio_destroyed.end(); ++lhmi) {
412  if (fnmatch(lhmi->first.c_str(), type, 0) != 0) continue;
413 
414  BBioList &list = (*lhmi).second;
415  for (i = list.begin(); i != list.end(); ++i) {
416  BlackBoardInterfaceObserver *bbio = i->first;
417  for (std::list<std::string>::iterator pi = i->second.begin(); pi != i->second.end(); ++pi) {
418  if (fnmatch(pi->c_str(), id, 0) == 0) {
419  bbio->bb_interface_destroyed(type, id);
420  break;
421  }
422  }
423  }
424  }
425 
426  __bbio_mutex->lock();
427  __bbio_events -= 1;
428  process_bbio_queue();
429  __bbio_mutex->unlock();
430 }
431 
432 
433 void
434 BlackBoardNotifier::process_bbio_queue()
435 {
436  if ( ! __bbio_queue.empty() ) {
437  if (__bbio_events > 0 ) {
438  return;
439  } else {
440  while (! __bbio_queue.empty()) {
441  BBioQueueEntry &e = __bbio_queue.front();
442  if (e.first) { // register
443  add_observer(e.second, e.second->bbio_get_observed_create(), __bbio_created);
444  add_observer(e.second, e.second->bbio_get_observed_destroy(), __bbio_destroyed);
445  } else { // unregister
446  remove_observer(__bbio_created, e.second);
447  remove_observer(__bbio_destroyed, e.second);
448  }
449  __bbio_queue.pop_front();
450  }
451  }
452  }
453 }
454 
455 
456 /** Notify that writer has been added.
457  * @param interface the interface for which the event happened. It is not necessarily the
458  * instance which caused the event, but it must have the same mem serial.
459  * @param event_instance_serial the instance serial of the interface that caused the event
460  * @see BlackBoardInterfaceListener::bb_interface_writer_added()
461  */
462 void
464  unsigned int event_instance_serial) throw()
465 {
466  __bbil_writer_mutex->lock();
467  __bbil_writer_events += 1;
468  __bbil_writer_mutex->unlock();
469 
470  const char *uid = interface->uid();
471  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
472  __bbil_writer.equal_range(uid);
473  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
474  BlackBoardInterfaceListener *bbil = j->second;
475  if (! is_in_queue(/* remove op*/ false, __bbil_writer_queue, uid, bbil)) {
476  Interface *bbil_iface = bbil->bbil_writer_interface(uid);
477  if (bbil_iface != NULL ) {
478  bbil->bb_interface_writer_added(bbil_iface, event_instance_serial);
479  } else {
480  LibLogger::log_warn("BlackBoardNotifier",
481  "BBIL[%s] registered for writer events "
482  "(open) for '%s' but has no such interface",
483  bbil->bbil_name(), uid);
484  }
485  }
486  }
487 
488  __bbil_writer_mutex->lock();
489  __bbil_writer_events -= 1;
490  process_writer_queue();
491  __bbil_writer_mutex->unlock();
492 }
493 
494 
495 /** Notify that writer has been removed.
496  * @param interface interface for which the writer has been removed
497  * @param event_instance_serial instance serial of the interface that caused the event
498  * @see BlackBoardInterfaceListener::bb_interface_writer_removed()
499  */
500 void
502  unsigned int event_instance_serial) throw()
503 {
504  __bbil_writer_mutex->lock();
505  __bbil_writer_events += 1;
506  __bbil_writer_mutex->unlock();
507 
508  const char *uid = interface->uid();
509  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
510  __bbil_writer.equal_range(uid);
511  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
512  BlackBoardInterfaceListener *bbil = j->second;
513  if (! is_in_queue(/* remove op*/ false, __bbil_data_queue, uid, bbil)) {
514  Interface *bbil_iface = bbil->bbil_writer_interface(uid);
515  if (bbil_iface != NULL ) {
516  bbil->bb_interface_writer_removed(bbil_iface, event_instance_serial);
517  } else {
518  LibLogger::log_warn("BlackBoardNotifier",
519  "BBIL[%s] registered for writer events "
520  "(close) for '%s' but has no such interface",
521  bbil->bbil_name(), uid);
522  }
523  }
524  }
525 
526  __bbil_writer_mutex->lock();
527  __bbil_writer_events -= 1;
528  process_writer_queue();
529  __bbil_writer_mutex->unlock();
530 }
531 
532 void
533 BlackBoardNotifier::process_writer_queue()
534 {
535  if ( ! __bbil_writer_queue.empty() ) {
536  if (__bbil_writer_events > 0 ) {
537  return;
538  } else {
539  while (! __bbil_writer_queue.empty()) {
540  BBilQueueEntry &e = __bbil_writer_queue.front();
541  if (e.op) { // register
542  add_listener(e.interface, e.listener, __bbil_writer);
543  } else { // unregister
544  remove_listener(e.interface, e.listener, __bbil_writer);
545  }
546  __bbil_writer_queue.pop_front();
547  }
548  }
549  }
550 }
551 
552 
553 /** Notify that reader has been added.
554  * @param interface interface for which the reader has been added
555  * @param event_instance_serial instance serial of the interface that caused the event
556  * @see BlackBoardInterfaceListener::bb_interface_reader_added()
557  */
558 void
560  unsigned int event_instance_serial) throw()
561 {
562  __bbil_reader_mutex->lock();
563  __bbil_reader_events += 1;
564  __bbil_reader_mutex->unlock();
565 
566  const char *uid = interface->uid();
567  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
568  __bbil_reader.equal_range(uid);
569  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
570  BlackBoardInterfaceListener *bbil = j->second;
571  if (! is_in_queue(/* remove op*/ false, __bbil_reader_queue, uid, bbil)) {
572  Interface *bbil_iface = bbil->bbil_reader_interface(uid);
573  if (bbil_iface != NULL ) {
574  bbil->bb_interface_reader_added(bbil_iface, event_instance_serial);
575  } else {
576  LibLogger::log_warn("BlackBoardNotifier",
577  "BBIL[%s] registered for reader events "
578  "(open) for '%s' but has no such interface",
579  bbil->bbil_name(), uid);
580  }
581  }
582  }
583 
584  __bbil_reader_mutex->lock();
585  __bbil_reader_events -= 1;
586  process_reader_queue();
587  __bbil_reader_mutex->unlock();
588 }
589 
590 
591 /** Notify that reader has been removed.
592  * @param interface interface for which the reader has been removed
593  * @param event_instance_serial instance serial of the interface that caused the event
594  * @see BlackBoardInterfaceListener::bb_interface_reader_removed()
595  */
596 void
598  unsigned int event_instance_serial) throw()
599 {
600  __bbil_reader_mutex->lock();
601  __bbil_reader_events += 1;
602  __bbil_reader_mutex->unlock();
603 
604  const char *uid = interface->uid();
605  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
606  __bbil_reader.equal_range(uid);
607  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
608  BlackBoardInterfaceListener *bbil = j->second;
609  if (! is_in_queue(/* remove op*/ false, __bbil_data_queue, uid, bbil)) {
610  Interface *bbil_iface = bbil->bbil_reader_interface(uid);
611  if (bbil_iface != NULL ) {
612  bbil->bb_interface_reader_removed(bbil_iface, event_instance_serial);
613  } else {
614  LibLogger::log_warn("BlackBoardNotifier",
615  "BBIL[%s] registered for reader events "
616  "(close) for '%s' but has no such interface",
617  bbil->bbil_name(), uid);
618  }
619  }
620  }
621 
622  __bbil_reader_mutex->lock();
623  __bbil_reader_events -= 1;
624  process_reader_queue();
625  __bbil_reader_mutex->unlock();
626 }
627 
628 
629 void
630 BlackBoardNotifier::process_reader_queue()
631 {
632  if ( ! __bbil_reader_queue.empty() ) {
633  if (__bbil_reader_events > 0 ) {
634  return;
635  } else {
636  while (! __bbil_reader_queue.empty()) {
637  BBilQueueEntry &e = __bbil_reader_queue.front();
638  if (e.op) { // register
639  add_listener(e.interface, e.listener, __bbil_reader);
640  } else { // unregister
641  remove_listener(e.interface, e.listener, __bbil_reader);
642  }
643  __bbil_reader_queue.pop_front();
644  }
645  }
646  }
647 }
648 
649 
650 /** Notify of data change.
651  * Notify all subscribers of the given interface of a data change.
652  * This also influences logging and sending data over the network so it is
653  * mandatory to call this function! The interface base class write method does
654  * that for you.
655  * @param interface interface whose subscribers to notify
656  * @see Interface::write()
657  * @see BlackBoardInterfaceListener::bb_interface_data_changed()
658  */
659 void
661 {
662  __bbil_data_mutex->lock();
663  __bbil_data_events += 1;
664  __bbil_data_mutex->unlock();
665 
666  const char *uid = interface->uid();
667  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
668  __bbil_data.equal_range(uid);
669  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
670  BlackBoardInterfaceListener *bbil = j->second;
671  if (! is_in_queue(/* remove op*/ false, __bbil_data_queue, uid, bbil)) {
672  Interface *bbil_iface = bbil->bbil_data_interface(uid);
673  if (bbil_iface != NULL ) {
674  bbil->bb_interface_data_changed(bbil_iface);
675  } else {
676  LibLogger::log_warn("BlackBoardNotifier",
677  "BBIL[%s] registered for data change events "
678  "for '%s' but has no such interface",
679  bbil->bbil_name(), uid);
680  }
681  }
682  }
683 
684  __bbil_data_mutex->lock();
685  __bbil_data_events -= 1;
686  if ( ! __bbil_data_queue.empty() ) {
687  if (__bbil_data_events == 0 ) {
688  while (! __bbil_data_queue.empty()) {
689  BBilQueueEntry &e = __bbil_data_queue.front();
690  if (e.op) { // register
691  add_listener(e.interface, e.listener, __bbil_data);
692  } else { // unregister
693  remove_listener(e.interface, e.listener, __bbil_data);
694  }
695  __bbil_data_queue.pop_front();
696  }
697  }
698  }
699  __bbil_data_mutex->unlock();
700 }
701 
702 
703 /** Notify of message received
704  * Notify all subscribers of the given interface of an incoming message
705  * This also influences logging and sending data over the network so it is
706  * mandatory to call this function! The interface base class write method does
707  * that for you.
708  * @param interface interface whose subscribers to notify
709  * @param message message which is being received
710  * @return false if any listener returned false, true otherwise
711  * @see BlackBoardInterfaceListener::bb_interface_message_received()
712  */
713 bool
715 {
716  __bbil_messages_mutex->lock();
717  __bbil_messages_events += 1;
718  __bbil_messages_mutex->unlock();
719 
720  bool enqueue = true;
721 
722  const char *uid = interface->uid();
723  std::pair<BBilMap::iterator, BBilMap::iterator> ret =
724  __bbil_messages.equal_range(uid);
725  for (BBilMap::iterator j = ret.first; j != ret.second; ++j) {
726  BlackBoardInterfaceListener *bbil = j->second;
727  if (! is_in_queue(/* remove op*/ false, __bbil_messages_queue, uid, bbil)) {
728  Interface *bbil_iface = bbil->bbil_message_interface(uid);
729  if (bbil_iface != NULL ) {
730  bool abort = ! bbil->bb_interface_message_received(bbil_iface, message);
731  if (abort) {
732  enqueue = false;
733  break;
734  }
735  } else {
736  LibLogger::log_warn("BlackBoardNotifier",
737  "BBIL[%s] registered for message events "
738  "for '%s' but has no such interface",
739  bbil->bbil_name(), uid);
740  }
741  }
742  }
743 
744  __bbil_messages_mutex->lock();
745  __bbil_messages_events -= 1;
746  if ( ! __bbil_messages_queue.empty() ) {
747  if (__bbil_messages_events == 0 ) {
748  while (! __bbil_messages_queue.empty()) {
749  BBilQueueEntry &e = __bbil_messages_queue.front();
750  if (e.op) { // register
751  add_listener(e.interface, e.listener, __bbil_messages);
752  } else { // unregister
753  remove_listener(e.interface, e.listener, __bbil_messages);
754  }
755  __bbil_messages_queue.pop_front();
756  }
757  }
758  }
759  __bbil_messages_mutex->unlock();
760 
761  return enqueue;
762 }
763 
764 } // end namespace fawkes
ObservedInterfaceLockMap::iterator ObservedInterfaceLockMapIterator
Type for iterator of lockable interface type hash sets.
void notify_of_reader_added(const Interface *interface, unsigned int event_instance_serial)
Notify that reader has been added.
Definition: notifier.cpp:559
ListenerRegisterFlag
Flags to constrain listener registration/updates.
Definition: blackboard.h:98
Interface * bbil_reader_interface(const char *iuid)
Get interface instance for given UID.
virtual bool bb_interface_message_received(Interface *interface, Message *message)
BlackBoard message received notification.
consider data events
Definition: blackboard.h:99
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
ObservedInterfaceLockMap * bbio_get_observed_destroy()
Get interface destriction type watch list.
void notify_of_interface_created(const char *type, const char *id)
Notify that an interface has been created.
Definition: notifier.cpp:368
consider reader events
Definition: blackboard.h:101
void lock() const
Lock list.
Definition: lock_map.h:100
virtual void bb_interface_destroyed(const char *type, const char *id)
BlackBoard interface destroyed notification.
void update_listener(BlackBoardInterfaceListener *listener, BlackBoard::ListenerRegisterFlag flag)
Update BB event listener.
Definition: notifier.cpp:103
InterfaceMap messages
Message received event subscriptions.
InterfaceMap writer
Writer event subscriptions.
void notify_of_writer_added(const Interface *interface, unsigned int event_instance_serial)
Notify that writer has been added.
Definition: notifier.cpp:463
Fawkes library namespace.
void unlock()
Unlock the mutex.
Definition: mutex.cpp:135
BlackBoardNotifier()
Constructor.
Definition: notifier.cpp:54
Mutex locking helper.
Definition: mutex_locker.h:33
Structure to hold maps for active subscriptions.
void notify_of_writer_removed(const Interface *interface, unsigned int event_instance_serial)
Notify that writer has been removed.
Definition: notifier.cpp:501
virtual void bb_interface_reader_removed(Interface *interface, unsigned int instance_serial)
A reading instance has been closed for a watched interface.
void unregister_observer(BlackBoardInterfaceObserver *observer)
Unregister BB interface observer.
Definition: notifier.cpp:341
Interface * bbil_message_interface(const char *iuid)
Get interface instance for given UID.
void notify_of_data_change(const Interface *interface)
Notify of data change.
Definition: notifier.cpp:660
InterfaceMap data
Data event subscriptions.
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
consider message received events
Definition: blackboard.h:100
void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: notifier.cpp:180
virtual void bb_interface_data_changed(Interface *interface)
BlackBoard data changed notification.
void notify_of_interface_destroyed(const char *type, const char *id)
Notify that an interface has been destroyed.
Definition: notifier.cpp:403
InterfaceMap reader
Reader event subscriptions.
void unlock() const
Unlock list.
Definition: lock_map.h:120
const char * uid() const
Get unique identifier of interface.
Definition: interface.cpp:687
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:162
BlackBoard interface observer.
std::list< QueueEntry > InterfaceQueue
Queue of additions/removal of interfaces.
Interface * bbil_data_interface(const char *iuid)
Get interface instance for given UID.
Interface * bbil_writer_interface(const char *iuid)
Get interface instance for given UID.
consider writer events
Definition: blackboard.h:102
ObservedInterfaceLockMap * bbio_get_observed_create()
Get interface creation type watch list.
virtual void bb_interface_reader_added(Interface *interface, unsigned int instance_serial)
A reading instance has been opened for a watched interface.
virtual void bb_interface_writer_added(Interface *interface, unsigned int instance_serial)
A writing instance has been opened for a watched interface.
bool notify_of_message_received(const Interface *interface, Message *message)
Notify of message received Notify all subscribers of the given interface of an incoming message This ...
Definition: notifier.cpp:714
void lock()
Lock this mutex.
Definition: mutex.cpp:89
virtual void bb_interface_writer_removed(Interface *interface, unsigned int instance_serial)
A writing instance has been closed for a watched interface.
const char * bbil_name() const
Get BBIL name.
virtual ~BlackBoardNotifier()
Destructor.
Definition: notifier.cpp:74
void register_observer(BlackBoardInterfaceObserver *observer)
Register BB interface observer.
Definition: notifier.cpp:279
Mutex mutual exclusion lock.
Definition: mutex.h:32
virtual void bb_interface_created(const char *type, const char *id)
BlackBoard interface created notification.
void notify_of_reader_removed(const Interface *interface, unsigned int event_instance_serial)
Notify that reader has been removed.
Definition: notifier.cpp:597
void register_listener(BlackBoardInterfaceListener *listener, BlackBoard::ListenerRegisterFlag flag)
Register BB event listener.
Definition: notifier.cpp:90
BlackBoard interface listener.