Fawkes API  Fawkes Development Version
remote.cpp
1 
2 /***************************************************************************
3  * remote.h - Remote BlackBoard access via Fawkes network protocol
4  *
5  * Created: Mon Mar 03 10:53:00 2008
6  * Copyright 2006-2015 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <blackboard/remote.h>
24 #include <blackboard/exceptions.h>
25 #include <blackboard/net/messages.h>
26 #include <blackboard/net/ilist_content.h>
27 #include <blackboard/net/interface_proxy.h>
28 #include <blackboard/internal/notifier.h>
29 #include <blackboard/internal/instance_factory.h>
30 
31 #include <interface/interface_info.h>
32 
33 #include <core/threading/thread.h>
34 #include <core/threading/mutex.h>
35 #include <core/threading/mutex_locker.h>
36 #include <core/threading/wait_condition.h>
37 #include <netcomm/fawkes/client.h>
38 #include <utils/time/time.h>
39 
40 #include <string>
41 #include <cstring>
42 #include <fnmatch.h>
43 #include <arpa/inet.h>
44 
45 namespace fawkes {
46 
47 /** @class RemoteBlackBoard <blackboard/remote.h>
48  * Remote BlackBoard.
49  * This class implements the access to a remote BlackBoard using the Fawkes
50  * network protocol.
51  *
52  * @author Tim Niemueller
53  */
54 
55 /** Constructor.
56  * @param client Fawkes network client to use.
57  */
59 {
60  __fnc = client;
61  __fnc_owner = false;
62 
63  if ( ! __fnc->connected() ) {
64  throw Exception("Cannot instantiate RemoteBlackBoard on unconnected client");
65  }
66 
67  __fnc->register_handler(this, FAWKES_CID_BLACKBOARD);
68 
69  __mutex = new Mutex();
70  __instance_factory = new BlackBoardInstanceFactory();
71 
72  __wait_mutex = new Mutex();
73  __wait_cond = new WaitCondition(__wait_mutex);
74 
75  __inbound_thread = NULL;
76  __m = NULL;
77 }
78 
79 
80 /** Constructor.
81  * This will internall create a fawkes network client that is used to communicate
82  * with the remote BlackBoard.
83  * @param hostname hostname to connect to
84  * @param port port to connect to
85  */
86 RemoteBlackBoard::RemoteBlackBoard(const char *hostname, unsigned short int port)
87 {
88  __fnc = new FawkesNetworkClient(hostname, port);
89  try {
90  __fnc->connect();
91  } catch (Exception &e) {
92  delete __fnc;
93  throw;
94  }
95 
96  __fnc_owner = true;
97 
98  if ( ! __fnc->connected() ) {
99  throw Exception("Cannot instantiate RemoteBlackBoard on unconnected client");
100  }
101 
102  __fnc->register_handler(this, FAWKES_CID_BLACKBOARD);
103 
104  __mutex = new Mutex();
105  __instance_factory = new BlackBoardInstanceFactory();
106 
107  __wait_mutex = new Mutex();
108  __wait_cond = new WaitCondition(__wait_mutex);
109 
110  __inbound_thread = NULL;
111  __m = NULL;
112 }
113 
114 
115 /** Destructor. */
117 {
118  __fnc->deregister_handler(FAWKES_CID_BLACKBOARD);
119  delete __mutex;
120  delete __instance_factory;
121 
122  for ( __pit = __proxies.begin(); __pit != __proxies.end(); ++__pit) {
123  delete __pit->second;
124  }
125 
126  if (__fnc_owner) {
127  __fnc->disconnect();
128  delete __fnc;
129  }
130 
131  delete __wait_cond;
132  delete __wait_mutex;
133 }
134 
135 
136 bool
138 {
139  return __fnc->connected();
140 }
141 
142 
143 void
144 RemoteBlackBoard::reopen_interfaces()
145 {
146  __proxies.lock();
147  __ipit = __invalid_proxies.begin();
148  while ( __ipit != __invalid_proxies.end() ) {
149  try {
150  Interface *iface = (*__ipit)->interface();
151  open_interface(iface->type(), iface->id(), iface->owner(), iface->is_writer(), iface);
152  iface->set_validity(true);
153  __ipit = __invalid_proxies.erase(__ipit);
154  } catch (Exception &e) {
155  // we failed to re-establish validity for the given interface, bad luck
156  ++__ipit;
157  }
158  }
159  __proxies.unlock();
160 }
161 
162 bool
164 {
165  bool rv = true;
166  try {
167  if ( ! __fnc->connected() ) {
168  __fnc->connect();
169 
170  reopen_interfaces();
171  }
172  } catch (...) {
173  rv = false;
174  }
175  return rv;
176 }
177 
178 
179 void
180 RemoteBlackBoard::open_interface(const char *type, const char *identifier, const char *owner,
181  bool writer, Interface *iface)
182 {
183  if ( ! __fnc->connected() ) {
184  throw Exception("Cannot instantiate remote interface, connection is dead");
185  }
186 
187  __mutex->lock();
188  if (__inbound_thread != NULL &&
190  strcmp(Thread::current_thread()->name(), __inbound_thread) == 0)
191  {
192  throw Exception("Cannot call open_interface() from inbound handler");
193  }
194  __mutex->unlock();
195 
196  bb_iopen_msg_t *om = (bb_iopen_msg_t *)calloc(1, sizeof(bb_iopen_msg_t));
197  strncpy(om->type, type, __INTERFACE_TYPE_SIZE);
198  strncpy(om->id, identifier, __INTERFACE_ID_SIZE);
199  memcpy(om->hash, iface->hash(), __INTERFACE_HASH_SIZE);
200 
201  FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_BLACKBOARD,
202  writer ? MSG_BB_OPEN_FOR_WRITING : MSG_BB_OPEN_FOR_READING,
203  om, sizeof(bb_iopen_msg_t));
204 
205  __wait_mutex->lock();
206  __fnc->enqueue(omsg);
207  while (is_alive() &&
208  (! __m ||
209  ((__m->msgid() != MSG_BB_OPEN_SUCCESS) &&
210  (__m->msgid() != MSG_BB_OPEN_FAILURE))))
211  {
212  if ( __m ) {
213  __m->unref();
214  __m = NULL;
215  }
216  __wait_cond->wait();
217  }
218  __wait_mutex->unlock();
219 
220  if (!is_alive()) {
221  throw Exception("Connection died while trying to open %s::%s",
222  type, identifier);
223  }
224 
225  if ( __m->msgid() == MSG_BB_OPEN_SUCCESS ) {
226  // We got the interface, create internal storage and prepare instance for return
228  iface, writer);
229  __proxies[proxy->serial()] = proxy;
230  } else if ( __m->msgid() == MSG_BB_OPEN_FAILURE ) {
232  unsigned int error = ntohl(fm->error_code);
233  __m->unref();
234  __m = NULL;
235  if ( error == BB_ERR_WRITER_EXISTS ) {
236  throw BlackBoardWriterActiveException(identifier, type);
237  } else if ( error == BB_ERR_HASH_MISMATCH ) {
238  throw Exception("Hash mismatch for interface %s:%s", type, identifier);
239  } else if ( error == BB_ERR_UNKNOWN_TYPE ) {
240  throw Exception("Type %s unknown (%s::%s)", type, type, identifier);
241  } else if ( error == BB_ERR_WRITER_EXISTS ) {
242  throw BlackBoardWriterActiveException(identifier, type);
243  } else {
244  throw Exception("Could not open interface");
245  }
246  }
247 
248  __m->unref();
249  __m = NULL;
250 }
251 
252 Interface *
253 RemoteBlackBoard::open_interface(const char *type, const char *identifier, const char *owner, bool writer)
254 {
255  if ( ! __fnc->connected() ) {
256  throw Exception("Cannot instantiate remote interface, connection is dead");
257  }
258 
259  Interface *iface = __instance_factory->new_interface_instance(type, identifier);
260  try {
261  open_interface(type, identifier, owner, writer, iface);
262  } catch (Exception &e) {
263  __instance_factory->delete_interface_instance(iface);
264  throw;
265  }
266 
267  return iface;
268 }
269 
270 
271 Interface *
272 RemoteBlackBoard::open_for_reading(const char *type, const char *identifier, const char *owner)
273 {
274  return open_interface(type, identifier, owner, /* writer? */ false);
275 }
276 
277 
278 Interface *
279 RemoteBlackBoard::open_for_writing(const char *type, const char *identifier, const char *owner)
280 {
281  return open_interface(type, identifier, owner, /* writer? */ true);
282 }
283 
284 
285 std::list<Interface *>
287  const char *id_pattern, const char *owner)
288 {
289  std::list<Interface *> rv;
290 
291  InterfaceInfoList *infl = list_all();
292  for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) {
293  // ensure 0-termination
294  char type[__INTERFACE_TYPE_SIZE + 1];
295  char id[__INTERFACE_ID_SIZE + 1];
296  type[__INTERFACE_TYPE_SIZE] = 0;
297  id[__INTERFACE_TYPE_SIZE] = 0;
298  strncpy(type, i->type(), __INTERFACE_TYPE_SIZE);
299  strncpy(id, i->id(), __INTERFACE_ID_SIZE);
300 
301  if ((fnmatch(type_pattern, type, 0) == FNM_NOMATCH) ||
302  (fnmatch(id_pattern, id, 0) == FNM_NOMATCH) ) {
303  // type or ID prefix does not match, go on
304  continue;
305  }
306 
307  try {
308  Interface *iface = open_for_reading((*i).type(), (*i).id(), owner);
309  rv.push_back(iface);
310  } catch (Exception &e) {
311  for (std::list<Interface *>::iterator j = rv.begin(); j != rv.end(); ++j) {
312  close(*j);
313  }
314  throw;
315  }
316  }
317 
318  return rv;
319 }
320 
321 
322 /** Close interface.
323  * @param interface interface to close
324  */
325 void
327 {
328  if ( interface == NULL ) return;
329 
330  unsigned int serial = interface->serial();
331 
332  if ( __proxies.find(serial) != __proxies.end() ) {
333  delete __proxies[serial];
334  __proxies.erase(serial);
335  }
336 
337  if ( __fnc->connected() ) {
338  // We cannot "officially" close it, if we are disconnected it cannot be used anyway
339  bb_iserial_msg_t *sm = (bb_iserial_msg_t *)calloc(1, sizeof(bb_iserial_msg_t));
340  sm->serial = htonl(interface->serial());
341 
342  FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_BLACKBOARD,
343  MSG_BB_CLOSE,
344  sm, sizeof(bb_iserial_msg_t));
345  __fnc->enqueue(omsg);
346  }
347 
348  __instance_factory->delete_interface_instance(interface);
349 }
350 
351 
354 {
355  __mutex->lock();
356  if (__inbound_thread != NULL &&
357  strcmp(Thread::current_thread()->name(), __inbound_thread) == 0)
358  {
359  throw Exception("Cannot call list_all() from inbound handler");
360  }
361  __mutex->unlock();
362 
363  InterfaceInfoList *infl = new InterfaceInfoList();
364 
365  FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_BLACKBOARD,
366  MSG_BB_LIST_ALL);
367  __wait_mutex->lock();
368  __fnc->enqueue(omsg);
369  while (! __m ||
370  (__m->msgid() != MSG_BB_INTERFACE_LIST)) {
371  if ( __m ) {
372  __m->unref();
373  __m = NULL;
374  }
375  __wait_cond->wait();
376  }
377  __wait_mutex->unlock();
378 
380  while ( bbilc->has_next() ) {
381  size_t iisize;
382  bb_iinfo_msg_t *ii = bbilc->next(&iisize);
383  bool has_writer = ii->writer_readers & htonl(0x80000000);
384  unsigned int num_readers = ntohl(ii->writer_readers & htonl(0x7FFFFFFF));
385  infl->append(ii->type, ii->id, ii->hash, ntohl(ii->serial),
386  has_writer, num_readers, std::list<std::string>(), std::string(),
388  }
389 
390  __m->unref();
391  __m = NULL;
392 
393  return infl;
394 }
395 
396 
398 RemoteBlackBoard::list(const char *type_pattern, const char *id_pattern)
399 {
400  __mutex->lock();
401  if (__inbound_thread != NULL &&
402  strcmp(Thread::current_thread()->name(), __inbound_thread) == 0)
403  {
404  throw Exception("Cannot call list() from inbound handler");
405  }
406  __mutex->unlock();
407 
408  InterfaceInfoList *infl = new InterfaceInfoList();
409 
410  bb_ilistreq_msg_t *om =
411  (bb_ilistreq_msg_t *)calloc(1, sizeof(bb_ilistreq_msg_t));
412  strncpy(om->type_pattern, type_pattern, __INTERFACE_TYPE_SIZE);
413  strncpy(om->id_pattern, id_pattern, __INTERFACE_ID_SIZE);
414 
415  FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_BLACKBOARD,
416  MSG_BB_LIST,
417  om,
418  sizeof(bb_ilistreq_msg_t));
419 
420  __wait_mutex->lock();
421  __fnc->enqueue(omsg);
422  while (! __m ||
423  (__m->msgid() != MSG_BB_INTERFACE_LIST)) {
424  if ( __m ) {
425  __m->unref();
426  __m = NULL;
427  }
428  __wait_cond->wait();
429  }
430  __wait_mutex->unlock();
431 
434  while ( bbilc->has_next() ) {
435  size_t iisize;
436  bb_iinfo_msg_t *ii = bbilc->next(&iisize);
437  bool has_writer = ii->writer_readers & htonl(0x80000000);
438  unsigned int num_readers = ntohl(ii->writer_readers & htonl(0x7FFFFFFF));
439  infl->append(ii->type, ii->id, ii->hash, ntohl(ii->serial),
440  has_writer, num_readers, std::list<std::string>(), std::string(),
442  }
443 
444  __m->unref();
445  __m = NULL;
446 
447  return infl;
448 }
449 
450 
451 /** We are no longer registered in Fawkes network client.
452  * Ignored.
453  * @param id the id of the calling client
454  */
455 void
456 RemoteBlackBoard::deregistered(unsigned int id) throw()
457 {
458 }
459 
460 
461 void
463  unsigned int id) throw()
464 {
465  __mutex->lock();
466  __inbound_thread = Thread::current_thread()->name();
467  __mutex->unlock();
468 
469  if ( m->cid() == FAWKES_CID_BLACKBOARD ) {
470  unsigned int msgid = m->msgid();
471  try {
472  if ( msgid == MSG_BB_DATA_CHANGED ) {
473  unsigned int serial = ntohl(((unsigned int *)m->payload())[0]);
474  if ( __proxies.find(serial) != __proxies.end() ) {
475  __proxies[serial]->process_data_changed(m);
476  }
477  } else if (msgid == MSG_BB_INTERFACE_MESSAGE) {
478  unsigned int serial = ntohl(((unsigned int *)m->payload())[0]);
479  if ( __proxies.find(serial) != __proxies.end() ) {
480  __proxies[serial]->process_interface_message(m);
481  }
482  } else if (msgid == MSG_BB_READER_ADDED) {
484  if ( __proxies.find(ntohl(esm->serial)) != __proxies.end() ) {
485  __proxies[ntohl(esm->serial)]->reader_added(ntohl(esm->event_serial));
486  }
487  } else if (msgid == MSG_BB_READER_REMOVED) {
489  if ( __proxies.find(ntohl(esm->serial)) != __proxies.end() ) {
490  __proxies[ntohl(esm->serial)]->reader_removed(ntohl(esm->event_serial));
491  }
492  } else if (msgid == MSG_BB_WRITER_ADDED) {
494  if ( __proxies.find(ntohl(esm->serial)) != __proxies.end() ) {
495  __proxies[ntohl(esm->serial)]->writer_added(ntohl(esm->event_serial));
496  }
497  } else if (msgid == MSG_BB_WRITER_REMOVED) {
499  if ( __proxies.find(ntohl(esm->serial)) != __proxies.end() ) {
500  __proxies[ntohl(esm->serial)]->writer_removed(ntohl(esm->event_serial));
501  }
502  } else if (msgid == MSG_BB_INTERFACE_CREATED) {
503  bb_ievent_msg_t *em = m->msg<bb_ievent_msg_t>();
505  } else if (msgid == MSG_BB_INTERFACE_DESTROYED) {
506  bb_ievent_msg_t *em = m->msg<bb_ievent_msg_t>();
508  } else {
509  __wait_mutex->lock();
510  __m = m;
511  __m->ref();
512  __wait_cond->wake_all();
513  __wait_mutex->unlock();
514  }
515  } catch (Exception &e) {
516  // Bam, you're dead. Ok, not now, we just ignore that this shit happened...
517  }
518  }
519 
520  __mutex->lock();
521  __inbound_thread = NULL;
522  __mutex->unlock();
523 }
524 
525 
526 void
527 RemoteBlackBoard::connection_died(unsigned int id) throw()
528 {
529  // mark all assigned interfaces as invalid
530  __proxies.lock();
531  for (__pit = __proxies.begin(); __pit != __proxies.end(); ++__pit) {
532  __pit->second->interface()->set_validity(false);
533  __invalid_proxies.push_back(__pit->second);
534  }
535  __proxies.clear();
536  __proxies.unlock();
537  __wait_cond->wake_all();
538 }
539 
540 
541 void
543 {
544 }
545 
546 } // end namespace fawkes
unsigned char hash[__INTERFACE_HASH_SIZE]
interface version hash
Definition: messages.h:81
uint32_t serial
instance serial to uniquely identify this instance (big endian)
Definition: messages.h:90
Interface * new_interface_instance(const char *type, const char *identifier)
Creates a new interface instance.
const char * owner() const
Get owner of interface.
Definition: interface.cpp:673
bool has_next()
Check if more list elements are available.
BlackBoard instance factory.
char type[__INTERFACE_TYPE_SIZE]
interface type name
Definition: messages.h:79
Wait until a given condition holds.
Requested interface type is unknown.
Definition: messages.h:59
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)
Open interface for writing.
Definition: remote.cpp:279
Simple Fawkes network client.
Definition: client.h:52
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:99
void notify_of_interface_created(const char *type, const char *id)
Notify that an interface has been created.
Definition: notifier.cpp:368
char type[__INTERFACE_TYPE_SIZE]
interface type name
Definition: messages.h:106
Message to identify an two interface instances.
Definition: messages.h:124
int64_t timestamp_sec
data or write timestamp, sec part
Definition: messages.h:97
Fawkes library namespace.
void unlock()
Unlock the mutex.
Definition: mutex.cpp:135
Message to identify an interface on open.
Definition: messages.h:78
void wake_all()
Wake up all waiting threads.
void disconnect()
Disconnect socket.
Definition: client.cpp:529
int64_t timestamp_usec
data or write timestamp, usec part
Definition: messages.h:98
const char * id() const
Get identifier of interface.
Definition: interface.cpp:661
void register_handler(FawkesNetworkClientHandler *handler, unsigned int component_id)
Register handler.
Definition: client.cpp:646
void enqueue(FawkesNetworkMessage *message)
Enqueue message to send.
Definition: client.cpp:587
unsigned int serial() const
Get instance serial of interface.
Representation of a message that is sent over the network.
Definition: message.h:75
void connect()
Connect to remote.
Definition: client.cpp:417
bb_iinfo_msg_t * next(size_t *size)
Get next plugin from list.
A class for handling time.
Definition: time.h:91
virtual void deregistered(unsigned int id)
We are no longer registered in Fawkes network client.
Definition: remote.cpp:456
virtual void connection_established(unsigned int id)
Client has established a connection.
Definition: remote.cpp:542
MT * msgc() const
Get correctly parsed output.
Definition: message.h:154
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
Message for interface info.
Definition: messages.h:86
You tried to open an interface for writing but there is already a writing instance for this interface...
Definition: messages.h:62
uint32_t error_code
Error code.
Definition: messages.h:149
uint32_t event_serial
instance serial to unique identify instance that caused the event.
Definition: messages.h:126
virtual InterfaceInfoList * list(const char *type_pattern, const char *id_pattern)
Get list of interfaces matching type and ID patterns.
Definition: remote.cpp:398
const unsigned char * hash() const
Get interface hash.
Definition: interface.cpp:294
Interface information list.
const char * type() const
Get type of interface.
Definition: interface.cpp:651
char id[__INTERFACE_ID_SIZE]
interface instance ID
Definition: messages.h:88
virtual void close(Interface *interface)
Close interface.
Definition: remote.cpp:326
char id_pattern[__INTERFACE_ID_SIZE]
ID pattern.
Definition: messages.h:74
Base class for exceptions in Fawkes.
Definition: exception.h:36
unsigned short serial() const
Get instance serial of interface.
Definition: interface.cpp:697
virtual ~RemoteBlackBoard()
Destructor.
Definition: remote.cpp:116
uint32_t serial
instance serial to unique identify own instance
Definition: messages.h:125
uint32_t writer_readers
combined writer reader information.
Definition: messages.h:92
void delete_interface_instance(Interface *interface)
Destroy an interface instance.
char type[__INTERFACE_TYPE_SIZE]
interface type name
Definition: messages.h:87
virtual bool try_aliveness_restore()
Try to restore the aliveness of the BlackBoard instance.
Definition: remote.cpp:163
Interface proxy for remote BlackBoard.
virtual void inbound_received(FawkesNetworkMessage *msg, unsigned int id)
Called for incoming messages.
Definition: remote.cpp:462
void notify_of_interface_destroyed(const char *type, const char *id)
Notify that an interface has been destroyed.
Definition: notifier.cpp:403
void ref()
Increment reference count.
Definition: refcount.cpp:70
unsigned char hash[__INTERFACE_HASH_SIZE]
interface version hash
Definition: messages.h:89
The hashes of the interfaces do not match.
Definition: messages.h:60
static Thread * current_thread()
Get the Thread instance of the currently running thread.
Definition: thread.cpp:1318
const char * name() const
Get name of thread.
Definition: thread.h:95
BlackBoardNotifier * __notifier
Notifier for BB events.
Definition: blackboard.h:122
virtual void connection_died(unsigned int id)
Client connection died.
Definition: remote.cpp:527
void wait()
Wait for the condition forever.
void append(const char *type, const char *id, const unsigned char *hash, unsigned int serial, bool has_writer, unsigned int num_readers, const std::list< std::string > &readers, const std::string &writer, const Time &timestamp)
Append an interface info.
bool is_writer() const
Check if this is a writing instance.
Definition: interface.cpp:440
char id[__INTERFACE_ID_SIZE]
interface instance ID
Definition: messages.h:80
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:301
uint32_t serial
instance serial to unique identify this instance
Definition: messages.h:116
RemoteBlackBoard(FawkesNetworkClient *client)
Constructor.
Definition: remote.cpp:58
char type_pattern[__INTERFACE_TYPE_SIZE]
type pattern
Definition: messages.h:73
virtual InterfaceInfoList * list_all()
Get list of all currently existing interfaces.
Definition: remote.cpp:353
void deregister_handler(unsigned int component_id)
Deregister handler.
Definition: client.cpp:665
Message for interface events.
Definition: messages.h:105
void set_validity(bool valid)
Mark this interface invalid.
Definition: interface.cpp:454
Message to request constrained interface list.
Definition: messages.h:72
BlackBoard interface list content.
Definition: ilist_content.h:35
Message to identify an interface instance.
Definition: messages.h:115
void lock()
Lock this mutex.
Definition: mutex.cpp:89
bool connected() const
Check if connection is alive.
Definition: client.cpp:823
Thrown if a writer is already active on an interface that writing has been requested for...
Definition: exceptions.h:121
MT * msg() const
Get correctly casted payload.
Definition: message.h:115
Mutex mutual exclusion lock.
Definition: mutex.h:32
char id[__INTERFACE_ID_SIZE]
interface instance ID
Definition: messages.h:107
virtual bool is_alive() const
Check if the BlackBoard is still alive.
Definition: remote.cpp:137
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)
Open interface for reading.
Definition: remote.cpp:272
std::list< Interface * > open_multiple_for_reading(const char *interface_type, const char *id_pattern="*", const char *owner=NULL)
Open multiple interfaces for reading.
Definition: remote.cpp:286
Message to send update data.
Definition: messages.h:148