Fawkes API  Fawkes Development Version
interface.cpp
1 
2 /***************************************************************************
3  * interface.cpp - BlackBoard Interface
4  *
5  * Created: Mon Oct 09 18:54:50 2006
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 <core/exceptions/system.h>
24 #include <core/threading/mutex.h>
25 #include <core/threading/mutex_locker.h>
26 #include <core/threading/refc_rwlock.h>
27 #include <interface/interface.h>
28 #include <interface/mediators/interface_mediator.h>
29 #include <interface/mediators/message_mediator.h>
30 #include <utils/misc/strndup.h>
31 #include <utils/time/clock.h>
32 #include <utils/time/time.h>
33 
34 #include <cerrno>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <regex.h>
39 #include <typeinfo>
40 
41 namespace fawkes {
42 
43 /** @class InterfaceWriteDeniedException <interface/interface.h>
44  * This exception is thrown if a write has been attempted on a read-only interface.
45  * @see Interface::write()
46  * @ingroup Exceptions
47  */
48 
49 /** Constructor.
50  * @param type type of the interface which caused the exception
51  * @param id id of the interface which caused the exception
52  * @param msg additional informative message
53  */
55  const char *id,
56  const char *msg)
57 : Exception("This interface instance '%s' of type '%s' is not opened for writing. %s",
58  id,
59  type,
60  msg)
61 {
62 }
63 
64 /** @class InterfaceMessageEnqueueException <interface/interface.h>
65  * This exception is thrown if a write has been attempted on a read-only interface.
66  * @see Interface::write()
67  * @ingroup Exceptions
68  */
69 
70 /** Constructor.
71  * @param type type of the interface which caused the exception
72  * @param id id of the interface which caused the exception
73  */
75 : Exception("This interface instance '%s' of type '%s' IS opened for writing, but "
76  "messages can only be enqueued on reading interfaces.",
77  id,
78  type)
79 {
80 }
81 
82 /** @class InterfaceInvalidMessageException <interface/interface.h>
83  * This exception is thrown if a message has been queued in the interface which is
84  * not recognized by the interface.
85  * @ingroup Exceptions
86  */
87 
88 /** Constructor.
89  * @param interface interface that the invalid message was enqueued to
90  * @param message enqueued message
91  */
93  const Message * message)
94 : Exception("Message of type '%s' cannot be enqueued in interface of type '%s'",
95  message->type(),
96  interface->type())
97 {
98 }
99 
100 /** @class InterfaceInvalidException <interface/interface.h>
101  * This exception is thrown if an interface is invalid and it is attempted to call
102  * read()/write().
103  * @ingroup Exceptions
104  */
105 
106 /** Constructor.
107  * @param interface invalid interface that the operation was tried on
108  * @param method the method that was tried to execute
109  */
111 : Exception("The interface %s (instance serial %s) is invalid. You cannot call %s anymore.",
112  interface->uid(),
113  interface->serial().get_string().c_str(),
114  method)
115 {
116 }
117 
118 /** @class Interface <interface/interface.h>
119  * Base class for all Fawkes BlackBoard interfaces.
120  *
121  * Interfaces are identified by a type and an ID. The type is just a
122  * textual representation of the class name. The ID identifies a
123  * specific instance of this interface type. Additionally each
124  * interface has a hash. The hash is an MD5 digest of the XML config
125  * file that was fed to the interface generator to create the
126  * interface. It is used to detect incompatible versions of the same
127  * interface type.
128  *
129  * Interfaces have at least two sections of memory which contains a
130  * struct composed of the internal data of the interface. The first is
131  * shared with either the LocalBlackBoard instance (and hence all
132  * other instances of the interface) or with a transmission thread of
133  * a RemoteBlackBoard. The second is a private copy of the data. The
134  * data is copied between the shared and private section only upon
135  * request. Interfaces are either reading or writing, denoting their
136  * kind of access towards the shared memory section. At any point in
137  * time there may at most exist one writer for an interface, but any
138  * number of readers. The shared section is protected by a
139  * ReadWriteLock. For a writer, a call to write() will copy the data
140  * from the private to the shared section. For a reader, a call to
141  * read() will copy the data from the shared to the private
142  * section. Upon opening the interface, the private section is copied
143  * once from the shared section, even when opening a writer.
144  *
145  * An interface has an internal timestamp. This timestamp indicates
146  * when the data in the interface has been modified last. The
147  * timestamp is usually automatically updated. But it some occasions
148  * the writer may choose to provide its own timestamp data. This can
149  * be useful for example for an interface providing hardware data to
150  * give the exact capture time. In the automatic case nothing has to
151  * be done manually. The timestamp is updated automatically by calling
152  * the write() method if and only if the data in the interface has
153  * actually been modified. The reader can call changed() to see if the
154  * data changed. In the non-automatic case the writer must first
155  * disable automatic timestamping using set_auto_timestamping(). Then
156  * it must provide a timestamp everytime before calling write(). Note
157  * that setting the timestamp already marks the interface as having
158  * changed. So set the timestamp only if the data has changed and the
159  * readers should see this.
160  *
161  * An interface provides support for buffers. Like the shared and
162  * private memory sections described above, buffers are additional
163  * memory sections that can be used to save data from the shared
164  * section or save or restore from and to the private memory
165  * section. One example use case is to save the current shared memory
166  * content at one point in time at a specific main loop hook, and
167  * restore it only later at a suitable time in another continuous
168  * thread. Another useful application is to keep a history for
169  * hysteresis processing, or to observe the development of the values
170  * in an interface.
171  *
172  * Interfaces are not created directly, but rather by using the
173  * interface generator.
174  *
175  * @author Tim Niemueller
176  */
177 
178 /** @var Interface::data_ptr
179  * Pointer to local memory storage
180  */
181 
182 /** @var Interface::data_ts
183  * Pointer to data casted to timestamp struct. This assumes that the very
184  * first two entries are 64 bit wide signed integers containing seconds and
185  * microseconds since the Unix epoch.
186  */
187 
188 /** @var Interface::data_size
189  * Minimal data size to hold data storage.
190  */
191 
192 /** @var Interface::data_refreshed
193  * Indicator if data can be considered "current", i.e. the latest available.
194  * This must be set by all methods that manipulate internal data or the
195  * timestamp. Always set to true by @ref set_field.
196  * Only if set to true a call to write() will update data_ts.
197  */
198 
199 /** @var Interface::data_changed
200  * Indicator if the current data is different from the last call to write()
201  * This must is automatically updated by @ref set_field.
202  */
203 
204 /** @fn bool Interface::message_valid(const Message *message) const = 0
205  * Check if the message is valid and can be enqueued.
206  * @param message The message to check
207  * @return true, if the message is valid and may be enqueued, false otherwise
208  *
209  * @fn bool Interface::create_message(const char *type) const = 0
210  * Create message based on type name.
211  * This will create a new message of the given type. The type must be
212  * given without the InterfaceName:: prefix but just the plain class
213  * name of the message.
214  * @param type message type
215  * @return message of the given type, empty
216  * @exception UnknownTypeException thrown if this interface cannot
217  * create a message of the given type.
218  *
219  * @fn void Interface::copy_values(const Interface *interface) = 0
220  * Copy values from another interface.
221  * The operation will only succeed if the supplied interface is of the same
222  * type as this instance.
223  * @param interface interface to copy from
224  *
225  * @fn const char * Interface::enum_tostring(const char *enumtype, int val) const
226  * Convert arbitrary enum value to string.
227  * Given the string representation of the enum type and the value this method
228  * returns the string representation of the specific value, or the string
229  * UNKNOWN if the value is not defined. An exception is thrown if the enum
230  * type is invalid.
231  * @param enumtype enum type as string
232  * @param val value to convert
233  * @return string representation of value
234  * @exception UnknownTypeException thrown if enumtype is not specified for
235  * interface.
236  */
237 
238 /** Constructor */
240 {
241  write_access_ = false;
242  rwlock_ = NULL;
243  valid_ = true;
244  next_message_id_ = 0;
245  num_fields_ = 0;
246  fieldinfo_list_ = NULL;
247  messageinfo_list_ = NULL;
248  clock_ = Clock::instance();
249  timestamp_ = new Time(0, 0);
250  local_read_timestamp_ = new Time(0, 0);
251  auto_timestamping_ = true;
252  owner_ = strdup("?");
253  data_changed = false;
254  data_refreshed = false;
255  memset(hash_, 0, INTERFACE_HASH_SIZE_);
256  memset(hash_printable_, 0, INTERFACE_HASH_SIZE_ * 2 + 1);
257 
258  data_ptr = NULL;
259  data_size = 0;
260 
261  buffers_ = NULL;
262  num_buffers_ = 0;
263 
264  message_queue_ = new MessageQueue();
265  data_mutex_ = new Mutex();
266 }
267 
268 /** Destructor */
270 {
271  if (rwlock_)
272  rwlock_->unref();
273  delete data_mutex_;
274  delete message_queue_;
275  if (buffers_)
276  free(buffers_);
277  // free fieldinfo list
278  interface_fieldinfo_t *finfol = fieldinfo_list_;
279  while (finfol) {
280  fieldinfo_list_ = fieldinfo_list_->next;
281  free(finfol);
282  finfol = fieldinfo_list_;
283  }
284  // free messageinfo list
285  interface_messageinfo_t *minfol = messageinfo_list_;
286  while (minfol) {
287  messageinfo_list_ = messageinfo_list_->next;
288  free(minfol);
289  minfol = messageinfo_list_;
290  }
291  delete timestamp_;
292  delete local_read_timestamp_;
293  if (owner_)
294  free(owner_);
295 }
296 
297 /** Get interface hash.
298  * The interface is a unique version identifier of an interface. It is
299  * the has of the input XML file during the generation of the
300  * interface. It is meant to be used to ensure that all sides are
301  * using the exact same version of an interface.
302  * @return constant byte string containing the hash value of hash_size() length
303  */
304 const unsigned char *
306 {
307  return hash_;
308 }
309 
310 /** Get printable interface hash.
311  * @return printable version of hash()
312  */
313 const char *
315 {
316  return hash_printable_;
317 }
318 
319 /** Set hash. Never use directly.
320  * @param ihash interface hash
321  */
322 void
323 Interface::set_hash(unsigned char *ihash)
324 {
325  memcpy(hash_, ihash, INTERFACE_HASH_SIZE_);
326  for (size_t s = 0; s < INTERFACE_HASH_SIZE_; ++s) {
327  snprintf(&hash_printable_[s * 2], 3, "%02X", hash_[s]);
328  }
329 }
330 
331 /** Add an entry to the field info list.
332  * Never use directly, use the interface generator instead. The info list
333  * is used for introspection purposes to allow for iterating over all fields
334  * of an interface.
335  * @param type field type
336  * @param name name of the field, this is referenced, not copied
337  * @param length length of the field
338  * @param value pointer to the value in the data struct
339  * @param enumtype name of the enum type, valid only if type == IFT_ENUM.
340  * @param enum_map enum value map
341  */
342 void
344  const char * name,
345  size_t length,
346  void * value,
347  const char * enumtype,
348  const interface_enum_map_t *enum_map)
349 {
350  interface_fieldinfo_t *infol = fieldinfo_list_;
352 
353  newinfo->type = type;
354  newinfo->enumtype = enumtype;
355  newinfo->name = name;
356  newinfo->length = length;
357  newinfo->value = value;
358  newinfo->enum_map = enum_map;
359  newinfo->next = NULL;
360 
361  if (infol == NULL) {
362  // first entry
363  fieldinfo_list_ = newinfo;
364  } else {
365  // append to list
366  while (infol->next != NULL) {
367  infol = infol->next;
368  }
369  infol->next = newinfo;
370  }
371 
372  ++num_fields_;
373 }
374 
375 /** Add an entry to the message info list.
376  * Never use directly, use the interface generator instead. The info list
377  * is used for introspection purposes to allow for iterating over all message
378  * types of an interface.
379  * @param type the type of the message
380  */
381 void
382 Interface::add_messageinfo(const char *type)
383 {
384  interface_messageinfo_t *infol = messageinfo_list_;
385  interface_messageinfo_t *newinfo =
387 
388  newinfo->type = type;
389  newinfo->next = NULL;
390 
391  if (infol == NULL) {
392  // first entry
393  messageinfo_list_ = newinfo;
394  } else {
395  // append to list
396  while (infol->next != NULL) {
397  infol = infol->next;
398  }
399  infol->next = newinfo;
400  }
401 }
402 
403 /** Obtain a list of textual representations of the message types
404  * available for this interface.
405  * @return the message types
406  */
407 std::list<const char *>
409 {
410  std::list<const char *> types;
411  interface_messageinfo_t *cur = messageinfo_list_;
412 
413  while (cur != NULL) {
414  types.push_back(cur->type);
415  cur = cur->next;
416  }
417 
418  return types;
419 }
420 
421 /** Get size of interface hash.
422  * Returns the size in bytes of the interface hash. This depends on the used hash.
423  * @return size of interface hash string
424  */
425 size_t
427 {
428  return INTERFACE_HASH_SIZE_;
429 }
430 
431 /** Get data chunk.
432  * Use sparsely
433  * @return const pointer to the data chunk
434  */
435 const void *
437 {
438  return data_ptr;
439 }
440 
441 /** Check if this is a writing instance.
442  * @return true if this is a writing instance, false otherwise
443  */
444 bool
446 {
447  return write_access_;
448 }
449 
450 /** Mark this interface invalid.
451  * An interface can become invalid, for example if the connection of a
452  * RemoteBlackBoard dies. In this case the interface becomes invalid
453  * and successive read()/write() calls will throw an
454  * InterfaceInvalidException.
455  * @param valid true to mark the interface valid or false to mark it invalid
456  */
457 void
459 {
460  rwlock_->lock_for_write();
461  valid_ = valid;
462  rwlock_->unlock();
463 }
464 
465 /** Check validity of interface.
466  * @return true if interface is valid, false otherwise
467  */
468 bool
470 {
471  return valid_;
472 }
473 
474 /** Read from BlackBoard into local copy.
475  * @exception InterfaceInvalidException thrown if the interface has
476  * been marked invalid
477  */
478 void
480 {
481  rwlock_->lock_for_read();
482  data_mutex_->lock();
483  if (valid_) {
484  memcpy(data_ptr, mem_data_ptr_, data_size);
485  *local_read_timestamp_ = *timestamp_;
487  } else {
488  data_mutex_->unlock();
489  rwlock_->unlock();
490  throw InterfaceInvalidException(this, "read()");
491  }
492  data_mutex_->unlock();
493  rwlock_->unlock();
494 }
495 
496 /** Write from local copy into BlackBoard memory.
497  * @exception InterfaceInvalidException thrown if the interface has
498  * been marked invalid
499  */
500 void
502 {
503  if (!write_access_) {
504  throw InterfaceWriteDeniedException(type_, id_, "Cannot write.");
505  }
506 
507  rwlock_->lock_for_write();
508  data_mutex_->lock();
509  bool has_changed = false;
510  if (valid_) {
511  if (data_refreshed) {
512  if (auto_timestamping_)
513  timestamp_->stamp();
514  long sec = 0, usec = 0;
515  timestamp_->get_timestamp(sec, usec);
516  data_ts->timestamp_sec = sec;
517  data_ts->timestamp_usec = usec;
518  data_refreshed = false;
519  }
520  if (data_changed) {
521  has_changed = true;
522  data_changed = false;
523  }
524  memcpy(mem_data_ptr_, data_ptr, data_size);
525  } else {
526  data_mutex_->unlock();
527  rwlock_->unlock();
528  throw InterfaceInvalidException(this, "write()");
529  }
530  data_mutex_->unlock();
531  rwlock_->unlock();
532 
533  interface_mediator_->notify_of_data_refresh(this, has_changed);
534 }
535 
536 /** Get data size.
537  * @return size in bytes of data segment
538  */
539 unsigned int
541 {
542  return data_size;
543 }
544 
545 /** Set type, ID and UID.
546  * Sets type and ID, UID is generated automatically as Type::ID.
547  * @param type string, a maximum of INTERFACE_TYPE_SIZE_ bytes are copied
548  * @param ID string, a maximum of INTERFACE_ID_SIZE_ bytes are copied
549  */
550 void
551 Interface::set_type_id(const char *type, const char *id)
552 {
553  strncpy(type_, type, INTERFACE_TYPE_SIZE_);
554  strncpy(id_, id, INTERFACE_ID_SIZE_);
555  snprintf(uid_, INTERFACE_UID_SIZE_ + 1, "%s::%s", type_, id_);
556  // Enforce null-terminated strings. If the input was not properly
557  // null-terminated, this truncated the last character of the string.
558  type_[INTERFACE_TYPE_SIZE_] = 0;
559  id_[INTERFACE_ID_SIZE_] = 0;
560  uid_[INTERFACE_UID_SIZE_] = 0;
561 }
562 
563 /** Set instance serial.
564  * @param instance_serial instance serial
565  */
566 void
567 Interface::set_instance_serial(const Uuid &instance_serial)
568 {
569  instance_serial_ = instance_serial;
570 }
571 
572 /** Set mediators.
573  * @param iface_mediator interface mediator
574  * @param msg_mediator message mediator.
575  */
576 void
577 Interface::set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator)
578 {
579  interface_mediator_ = iface_mediator;
580  message_mediator_ = msg_mediator;
581 }
582 
583 /** Set memory data.
584  * @param serial mem serial
585  * @param real_ptr pointer to whole chunk
586  * @param data_ptr pointer to data chunk
587  */
588 void
589 Interface::set_memory(unsigned int serial, void *real_ptr, void *data_ptr)
590 {
591  mem_serial_ = serial;
592  mem_real_ptr_ = real_ptr;
593  mem_data_ptr_ = data_ptr;
594 }
595 
596 /** Set read/write info.
597  * @param write_access true to enable write access, false for read-only
598  * @param rwlock read/write lock for this interface
599  */
600 void
601 Interface::set_readwrite(bool write_access, RefCountRWLock *rwlock)
602 {
603  write_access_ = write_access;
604  rwlock_ = rwlock;
605 }
606 
607 /** Set owner name for interface.
608  * @param owner name of owner of interface
609  */
610 void
611 Interface::set_owner(const char *owner)
612 {
613  if (owner_)
614  free(owner_);
615  owner_ = NULL;
616  if (owner)
617  owner_ = strdup(owner);
618 }
619 
620 /** Check equality of two interfaces.
621  * Two interfaces are the same if their types and identifiers are
622  * equal. This does not mean that both interfaces are the very same
623  * instance for accessing the BlackBoard. Instead this just means that
624  * both instances will access the same chunk of memory in the
625  * BlackBoard and the instances MAY be the same. If you want to know
626  * if two instances are exactly the same compare the instance serials
627  * using the serial() method.
628  * @param comp interface to compare current instance with
629  * @return true, if interfaces point to the same data, false otherwise
630  */
631 bool
633 {
634  return ((strncmp(type_, comp.type_, sizeof(type_)) == 0)
635  && (strncmp(id_, comp.id_, sizeof(id_)) == 0));
636 }
637 
638 /** Check if interface is of given type.
639  * @param interface_type type to query
640  * @return true, if current instance is of given type, false otherwise
641  */
642 bool
643 Interface::oftype(const char *interface_type) const
644 {
645  return (strncmp(this->type_, interface_type, sizeof(this->type_)) == 0);
646 }
647 
648 /** Get type of interface.
649  * @return string with the type of the interface.
650  */
651 const char *
653 {
654  return type_;
655 }
656 
657 /** Get identifier of interface.
658  * @return string with the identifier of the interface.
659  */
660 const char *
662 {
663  return id_;
664 }
665 
666 /** Get owner of interface.
667  * The owner is an arbitrary name, usually a thread or plugin name
668  * for the entity which opened this specific interface instance.
669  * @return owner name
670  */
671 const char *
673 {
674  return owner_;
675 }
676 
677 /** Get unique identifier of interface.
678  * As the name suggests this ID denotes a unique memory instance of
679  * this interface in the blackboard. It is provided by the system and
680  * currently returns a string of the form "type::id", where type is
681  * replaced by the type returned by type() and id is the ID returned
682  * by id().
683  * @return string with the unique identifier of the interface.
684  */
685 const char *
687 {
688  return uid_;
689 }
690 
691 /** Get instance serial of interface.
692  * @return instance serial of the interface.
693  */
694 Uuid
696 {
697  return instance_serial_;
698 }
699 
700 /** Get memory serial of interface.
701  * @return memory serial of interface
702  */
703 unsigned int
705 {
706  return mem_serial_;
707 }
708 
709 /** Get timestamp of last write.
710  * Note that you need to call read() before this provides useful information.
711  * @return timestamp of last write.
712  */
713 const Time *
715 {
716  return timestamp_;
717 }
718 
719 /** Set timestamp.
720  * @param t time stamp to copy time from, if NULL current time is queried
721  * from clock.
722  */
723 void
725 {
726  if (auto_timestamping_)
727  throw Exception("Auto timestamping enabled, cannot "
728  "set explicit timestamp");
729  if (!write_access_)
730  throw Exception("Timestamp can only be set on writing "
731  "instance");
732 
733  if (t) {
734  *timestamp_ = t;
735  } else {
736  timestamp_->stamp();
737  }
738  data_changed = true;
739 }
740 
741 /** Set clock to use for timestamping.
742  * @param clock clock to use from now on
743  */
744 void
746 {
747  clock_ = clock;
748  timestamp_->set_clock(clock);
749 }
750 
751 /** Enable or disable automated timestamping.
752  * @param enabled true to enable automated timestamping, false to disable
753  */
754 void
756 {
757  auto_timestamping_ = enabled;
758 }
759 
760 /** Mark data as refreshed.
761  * This will mark the data as refreshed for a writing instance. On the
762  * next write, the data will be written with an updated timestamp (if
763  * auto timestamping is enabled), regardless of whether new data was
764  * actually set.
765  */
766 void
768 {
769  data_refreshed = true;
770 }
771 
772 /** Mark data as changed. There should be no sensible reason for
773  * user code to call this method. It is only used for remote blackboard
774  * synchronization. Will cause change notifications to be dispatched on
775  * write().
776  */
777 void
779 {
780  data_changed = true;
781 }
782 
783 /**
784  * @return Whether the data in this interface is actually different from the
785  * last time write() was called.
786  * @sa refreshed()
787  */
788 bool
790 {
791  return data_changed;
792 }
793 
794 /** Check if data has been refreshed.
795  * This method has slightly different semantics depending on whether
796  * this interface is a writing or a reading instance.
797  * For a reading instance:
798  * If the data has been refreshed this method will return
799  * true at least until the next call to read. From then on it will
800  * return false if the data has not been refreshed between the two
801  * read() calls and still true otherwise.
802  * For a writing instance:
803  * The data is considered to have changed if any of the interface field
804  * set methods has been called since the last write() call.
805  * @return true if data has been changed between the last call to
806  * read() and the one before (reading instance) or if any data field
807  * setter has been called since the last write() call (writing instance),
808  * false otherwise
809  */
810 bool
812 {
813  if (write_access_) {
814  return data_refreshed;
815  } else {
816  return (*timestamp_ != local_read_timestamp_);
817  }
818 }
819 
820 /** Set from a raw data chunk.
821  * This allows for setting the interface data from a raw chunk. This
822  * is not useful in general but only in rare situations like network
823  * transmission. Do not use it unless you really know what you are
824  * doing. The method expects the chunk to be exactly of the size
825  * returned by datasize(). No check is done, a segfault will most
826  * likely occur if you provide invalid data.
827  * @param chunk data chunk, must be exactly of the size that is
828  * returned by datasize()
829  */
830 void
832 {
833  // This could be checked but should never happen with our generated
834  // interfaces anyway
835  // if ( data_ptr == NULL )
836  // throw NullPointerException("Interface not initialized");
837 
838  memcpy(data_ptr, chunk, data_size);
839 }
840 
841 /** Check if there is a writer for the interface.
842  * Use this method to determine if there is any open instance of the
843  * interface that is writing to the interface. This can also be the
844  * queried interface instance.
845  * @return true if a writer for the interface exists, false otherwise
846  */
847 bool
849 {
850  return interface_mediator_->exists_writer(this);
851 }
852 
853 /** Get the number of readers.
854  * Use this method to determine how many reading instances of the
855  * interface currently exist. If the current instance is a reading
856  * instance it will be included in the count number. To determine if
857  * you are the last man having this interface you can use the
858  * following code:
859  * @code
860  * // for a writing instance:
861  * if ( interface->num_readers == 0 ) {
862  * // we are the last one to have this interface open
863  * }
864  *
865  * // for a reading instance:
866  * if ( ! interface->has_writer() && (interface->num_readers() == 0) ) {
867  * // we are the last one to have this interface open
868  * }
869  * @endcode
870  * Note that this can result in a race condition. You have to be
871  * registered as a BlackBoardEventListener to be sure that you are
872  * really the last.
873  * @return number of readers
874  */
875 unsigned int
877 {
878  return interface_mediator_->num_readers(this);
879 }
880 
881 /** Get owner name of writing interface instance.
882  * @return name of owner of writing interface instance if a local one
883  * exists, an empty string otherwise.
884  */
885 std::string
887 {
888  return interface_mediator_->writer(this);
889 }
890 
891 /** Get owner names of reading interface instances.
892  * @return list of names of owners of instances opened for reading
893  */
894 std::list<std::string>
896 {
897  return interface_mediator_->readers(this);
898 }
899 
900 /** Enqueue message at end of queue.
901  * This appends the given message to the queue and transmits the
902  * message via the message mediator. The message is afterwards owned
903  * by the other side and will be unrefed and freed as soon as it has
904  * been processed. If you want to keep this message to read a feedback
905  * status you have to reference it _before_ enqueuing it!
906  * This can only be called on a reading interface instance.
907  * @param message Message to enqueue.
908  * @param proxy if set to true, this interface is only proxying the message and
909  * the sender is not overwritten
910  * @return message id after message has been queued
911  * @exception MessageAlreadyQueuedException thrown if the message has
912  * already been enqueued to an interface.
913  */
914 unsigned int
915 Interface::msgq_enqueue(Message *message, bool proxy)
916 {
917  if (write_access_) {
918  throw InterfaceMessageEnqueueException(type_, id_);
919  }
920 
921  if (message_valid(message)) {
922  message->set_interface(this, proxy);
923  message->set_id(next_msg_id());
924  // transmit might change the message id!
925  message_mediator_->transmit(message);
926  unsigned int msgid = message->id();
927  message->unref();
928  return msgid;
929  } else {
930  throw InterfaceInvalidMessageException(this, message);
931  }
932 }
933 
934 /** Enqueue copy of message at end of queue.
935 
936  * This method creates a copy of the message and enqueues it. Note
937  * that this way you cannot receive status message in the message,
938  * because the other side will not use your message instance but a
939  * copy instead.
940  *
941  * This is particularly useful if you call from an environment with
942  * automatic garbage collection that does not honor the referencing
943  * feature of message but rather just deletes it.
944  *
945  * This can only be called on a reading interface instance.
946  *
947  * @param message Message to enqueue.
948  * @return message id after message has been queued
949  * @exception MessageAlreadyQueuedException thrown if the message has already been
950  * enqueued to an interface.
951  */
952 unsigned int
954 {
955  if (write_access_) {
956  throw InterfaceMessageEnqueueException(type_, id_);
957  }
958  if (message == NULL) {
959  throw NullPointerException("Message may not be NULL");
960  }
961 
962  if (message_valid(message)) {
963  Message *mcopy = message->clone();
964  mcopy->set_interface(this);
965  mcopy->set_id(next_msg_id());
966  message_mediator_->transmit(mcopy);
967  unsigned int msgid = mcopy->id();
968  mcopy->unref();
969  message->set_id(msgid);
970  return msgid;
971  } else {
972  throw InterfaceInvalidMessageException(this, message);
973  }
974 }
975 
976 /** Enqueue message.
977  * This will enqueue the message without transmitting it via the
978  * message mediator. It can be useful, for example, to enqueue the
979  * message from an event callback.
980  *
981  * This can only be called on a writing interface instance.
982  *
983  * @param message message to enqueue, reference count will be incremented.
984  */
985 void
987 {
988  if (!write_access_) {
989  throw InterfaceWriteDeniedException(type_,
990  id_,
991  "Cannot work on message queue on "
992  "reading instance of an interface (append).");
993  }
994 
995  message->ref();
996  message_queue_->append(message);
997 }
998 
999 /** Remove message from queue.
1000  * Removes the given message from the queue. Note that if you
1001  * unref()ed the message after insertion this will most likely delete
1002  * the object. It is not safe to use the message after removing it
1003  * from the queue in general.
1004  *
1005  * This can only be called on a writing interface instance.
1006  *
1007  * @param message Message to remove.
1008  */
1009 void
1011 {
1012  if (!write_access_) {
1013  throw InterfaceWriteDeniedException(type_,
1014  id_,
1015  "Cannot work on message queue on "
1016  "reading instance of an interface (remove msg).");
1017  }
1018 
1019  return message_queue_->remove(message);
1020 }
1021 
1022 /** Remove message from queue.
1023  * Removes message with the given ID from the queue.
1024  * @param message_id Message ID to remove.
1025  * This can only be called on a writing interface instance.
1026  */
1027 void
1028 Interface::msgq_remove(unsigned int message_id)
1029 {
1030  if (!write_access_) {
1031  throw InterfaceWriteDeniedException(type_,
1032  id_,
1033  "Cannot work on message queue on "
1034  "reading instance of an interface (remove id).");
1035  }
1036 
1037  return message_queue_->remove(message_id);
1038 }
1039 
1040 /** Get size of message queue.
1041  * This can only be called on a writing interface instance.
1042  * @return number of messages in queue.
1043  */
1044 unsigned int
1046 {
1047  if (!write_access_) {
1048  throw InterfaceWriteDeniedException(type_,
1049  id_,
1050  "Cannot work on message queue on "
1051  "reading instance of an interface (size).");
1052  }
1053 
1054  return message_queue_->size();
1055 }
1056 
1057 /** Check if queue is empty.
1058  * This can only be called on a writing interface instance.
1059  * @return true if queue is empty, false otherwise
1060  */
1061 bool
1063 {
1064  if (!write_access_) {
1065  throw InterfaceWriteDeniedException(type_,
1066  id_,
1067  "Cannot work on message queue on "
1068  "reading instance of an interface (empty).");
1069  }
1070 
1071  return message_queue_->empty();
1072 }
1073 
1074 /** Flush all messages.
1075  * Deletes all messages from the queue.
1076  * This can only be called on a writing interface instance.
1077  */
1078 void
1080 {
1081  if (!write_access_) {
1082  throw InterfaceWriteDeniedException(type_,
1083  id_,
1084  "Cannot work on message queue on "
1085  "reading instance of an interface (flush).");
1086  }
1087 
1088  message_queue_->flush();
1089 }
1090 
1091 /** Lock message queue.
1092  * Lock the message queue. You have to do this * before using the
1093  * iterator safely.
1094  *
1095  * This can only be called on a writing interface instance.
1096  */
1097 void
1099 {
1100  if (!write_access_) {
1101  throw InterfaceWriteDeniedException(type_,
1102  id_,
1103  "Cannot work on message queue on "
1104  "reading instance of an interface (lock).");
1105  }
1106 
1107  message_queue_->lock();
1108 }
1109 
1110 /** Try to lock message queue.
1111  * Try to lock the message queue. Returns immediately and does not
1112  * wait for lock.
1113  *
1114  * This can only be called on a writing interface instance.
1115  * @return true, if the lock has been aquired, false otherwise.
1116  * @see lock()
1117  */
1118 bool
1120 {
1121  if (!write_access_) {
1122  throw InterfaceWriteDeniedException(type_,
1123  id_,
1124  "Cannot work on message queue on "
1125  "reading instance of an interface "
1126  "(msgq_try_lock).");
1127  }
1128 
1129  return message_queue_->try_lock();
1130 }
1131 
1132 /** Unlock message queue.
1133  * Give free the lock on the message queue.
1134  * This can only be called on a writing interface instance.
1135  */
1136 void
1138 {
1139  if (!write_access_) {
1140  throw InterfaceWriteDeniedException(type_,
1141  id_,
1142  "Cannot work on message queue on "
1143  "reading instance of an interface (unlock).");
1144  }
1145 
1146  message_queue_->unlock();
1147 }
1148 
1149 /** Get start iterator for message queue.
1150  * Not that you must have locked the queue before this operation!
1151  *
1152  * This can only be called on a writing interface instance.
1153  *
1154  * @return iterator to begin of message queue.
1155  * @exception NotLockedException thrown if message queue is not locked
1156  * during this operation.
1157  */
1160 {
1161  if (!write_access_) {
1162  throw InterfaceWriteDeniedException(type_,
1163  id_,
1164  "Cannot work on message queue on "
1165  "reading instance of an interface (begin).");
1166  }
1167 
1168  return message_queue_->begin();
1169 }
1170 
1171 /** Get end iterator for message queue.
1172  * Not that you must have locked the queue before this operation!
1173  *
1174  * This can only be called on a writing interface instance.
1175  *
1176  * @return iterator beyond end of message queue.
1177  * @exception NotLockedException thrown if message queue is not locked
1178  * during this operation.
1179  */
1182 {
1183  if (!write_access_) {
1184  throw InterfaceWriteDeniedException(type_,
1185  id_,
1186  "Cannot work on message queue on "
1187  "reading instance of an interface (end).");
1188  }
1189 
1190  return message_queue_->end();
1191 }
1192 
1193 /** Get the first message from the message queue.
1194  *
1195  * This can only be called on a writing interface instance.
1196  *
1197  * @return first message in queue or NULL if there is none
1198  */
1199 Message *
1201 {
1202  if (!write_access_) {
1203  throw InterfaceWriteDeniedException(type_,
1204  id_,
1205  "Cannot work on message queue on "
1206  "reading instance of an interface (first).");
1207  }
1208  return message_queue_->first();
1209 }
1210 
1211 /** Erase first message from queue.
1212  * This can only be called on a writing interface instance.
1213  */
1214 void
1216 {
1217  if (!write_access_) {
1218  throw InterfaceWriteDeniedException(type_,
1219  id_,
1220  "Cannot work on message queue on "
1221  "reading instance of an interface (pop).");
1222  }
1223 
1224  message_queue_->pop();
1225 }
1226 
1227 /** Get iterator over all fields of this interface instance.
1228  * @return field iterator pointing to the very first value
1229  */
1232 {
1233  return InterfaceFieldIterator(this, fieldinfo_list_);
1234 }
1235 
1236 /** Invalid iterator.
1237  * @return invalid iterator reprensenting the end.
1238  */
1241 {
1242  return InterfaceFieldIterator();
1243 }
1244 
1245 /** Get the number of fields in the interface.
1246  * @return the number of fields
1247  */
1248 unsigned int
1250 {
1251  return num_fields_;
1252 }
1253 
1254 /** Resize buffer array.
1255  * This resizes the memory region used to store data buffers.
1256  * @param num_buffers number of buffers to resize to (memory is allocated
1257  * as necessary, 0 frees the memory area).
1258  * @exception Exception thrown if resizing the memory section fails
1259  */
1260 void
1261 Interface::resize_buffers(unsigned int num_buffers)
1262 {
1263  data_mutex_->lock();
1264  if (num_buffers == 0) {
1265  if (buffers_ != NULL) {
1266  free(buffers_);
1267  buffers_ = NULL;
1268  num_buffers_ = 0;
1269  }
1270  } else {
1271  void *tmp = realloc(buffers_, (size_t)num_buffers * data_size);
1272  if (tmp == NULL) {
1273  data_mutex_->unlock();
1274  throw Exception(errno, "Resizing buffers for interface %s failed", uid_);
1275  } else {
1276  buffers_ = tmp;
1277  num_buffers_ = num_buffers;
1278  }
1279  }
1280  data_mutex_->unlock();
1281 }
1282 
1283 /** Get number of buffers.
1284  * @return number of buffers
1285  */
1286 unsigned int
1288 {
1289  return num_buffers_;
1290 }
1291 
1292 /** Copy data from private memory to buffer.
1293  * @param buffer buffer number to copy to
1294  */
1295 void
1297 {
1298  if (buffer >= num_buffers_) {
1299  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1300  }
1301 
1302  rwlock_->lock_for_read();
1303  data_mutex_->lock();
1304 
1305  void *buf = (char *)buffers_ + buffer * data_size;
1306 
1307  if (valid_) {
1308  memcpy(buf, mem_data_ptr_, data_size);
1309  } else {
1310  data_mutex_->unlock();
1311  rwlock_->unlock();
1312  throw InterfaceInvalidException(this, "copy_shared_to_buffer()");
1313  }
1314  data_mutex_->unlock();
1315  rwlock_->unlock();
1316 }
1317 
1318 /** Copy data from private memory to buffer.
1319  * @param buffer buffer number to copy to
1320  */
1321 void
1323 {
1324  if (buffer >= num_buffers_) {
1325  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1326  }
1327 
1328  data_mutex_->lock();
1329  void *buf = (char *)buffers_ + buffer * data_size;
1330  memcpy(buf, data_ptr, data_size);
1331  data_mutex_->unlock();
1332 }
1333 
1334 /** Copy data from buffer to private memory.
1335  * @param buffer buffer number to copy to
1336  */
1337 void
1338 Interface::read_from_buffer(unsigned int buffer)
1339 {
1340  if (buffer >= num_buffers_) {
1341  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1342  }
1343 
1344  data_mutex_->lock();
1345  void *buf = (char *)buffers_ + buffer * data_size;
1346  memcpy(data_ptr, buf, data_size);
1347  *local_read_timestamp_ = *timestamp_;
1349 
1350  data_mutex_->unlock();
1351 }
1352 
1353 /** Compare buffer to private memory.
1354  * @param buffer buffer number of buffer to compare to private memory
1355  * @return returns a number less than, equal to, or greater than zero
1356  * if the shared buffer if less than, equal to, or greater than the
1357  * private buffer respectively.
1358  */
1359 int
1360 Interface::compare_buffers(unsigned int buffer)
1361 {
1362  if (buffer >= num_buffers_) {
1363  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1364  }
1365 
1366  data_mutex_->lock();
1367  void *buf = (char *)buffers_ + buffer * data_size;
1368  int rv = memcmp(buf, data_ptr, data_size);
1369  data_mutex_->unlock();
1370 
1371  return rv;
1372 }
1373 
1374 /** Get time of a buffer.
1375  * @param buffer buffer number
1376  * @return timestamp stored in the interface
1377  */
1378 Time
1379 Interface::buffer_timestamp(unsigned int buffer)
1380 {
1381  if (buffer >= num_buffers_) {
1382  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1383  }
1384 
1385  MutexLocker lock(data_mutex_);
1386  void * buf = (char *)buffers_ + buffer * data_size;
1387  interface_data_ts_t *buf_ts = (interface_data_ts_t *)buf;
1388  return Time(buf_ts->timestamp_sec, buf_ts->timestamp_usec);
1389 }
1390 
1391 /** Get time of a buffer.
1392  * Use this method to query the time without allocating a new Time instance.
1393  * @param buffer buffer number
1394  * @param timestamp upon return contains the timestamp of the buffer.
1395  */
1396 void
1397 Interface::buffer_timestamp(unsigned int buffer, Time *timestamp)
1398 {
1399  if (buffer >= num_buffers_) {
1400  throw OutOfBoundsException("Buffer ID out of bounds", buffer, 0, num_buffers_);
1401  }
1402  if (timestamp == NULL) {
1403  throw NullPointerException("%s.buffer_timestamp: timestamp cannot be null", uid_);
1404  }
1405 
1406  MutexLocker lock(data_mutex_);
1407  void * buf = (char *)buffers_ + buffer * data_size;
1408  interface_data_ts_t *buf_ts = (interface_data_ts_t *)buf;
1409  timestamp->set_time(buf_ts->timestamp_sec, buf_ts->timestamp_usec);
1410 }
1411 
1412 /** Parse UID to type and ID strings.
1413  * Note that the returned values (type and id) must be freed once they are
1414  * no longer used. Also verifies lengths of the type and id strings.
1415  * @param uid UID to parse
1416  * @param type upon return contains the type part of the UID
1417  * @param id upon return contains the ID part
1418  */
1419 void
1420 Interface::parse_uid(const char *uid, std::string &type, std::string &id)
1421 {
1422  regex_t re;
1423  int ec = 0;
1424 // Requires in parse_uid()
1425 #define str(s) #s
1426 #define xstr(s) str(s)
1427  if ((ec = regcomp(&re,
1428  "^([a-zA-Z0-9]{1," xstr(INTERFACE_TYPE_SIZE_) "})::"
1429  "([a-zA-Z0-9 _/\\.-]{1," xstr(
1430  INTERFACE_ID_SIZE_) "})$",
1431  REG_EXTENDED))
1432  != 0) {
1433  char errbuf[1024];
1434  regerror(ec, &re, errbuf, 1024);
1435  throw Exception("Failed to created regular expression to parse UID (%s)", errbuf);
1436  }
1437  regmatch_t matches[3];
1438  if (regexec(&re, uid, 3, matches, 0) != 0) {
1439  regfree(&re);
1440  throw Exception("Failed to match UID %s, format error.", uid);
1441  }
1442 
1443  type.assign(&(uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1444  id.assign(&(uid[matches[2].rm_so]), matches[2].rm_eo - matches[2].rm_so);
1445 
1446  regfree(&re);
1447 }
1448 
1449 } // end namespace fawkes
This is supposed to be the central clock in Fawkes.
Definition: clock.h:35
static Clock * instance()
Clock initializer.
Definition: clock.cpp:63
Base class for exceptions in Fawkes.
Definition: exception.h:36
Interface field iterator.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
Definition: interface.h:74
InterfaceInvalidException(const Interface *interface, const char *method)
Constructor.
Definition: interface.cpp:110
This exception is thrown if a message has been queued in the interface which is not recognized by the...
Definition: interface.h:68
InterfaceInvalidMessageException(const Interface *interface, const Message *message)
Constructor.
Definition: interface.cpp:92
virtual unsigned int num_readers(const Interface *interface) const =0
Get number of readers.
virtual std::list< std::string > readers(const Interface *interface) const =0
Get owners of interfaces who opened for reading.
virtual void notify_of_data_refresh(const Interface *interface, bool has_changed)=0
Notify of data change.
virtual std::string writer(const Interface *interface) const =0
Get writer of interface.
virtual bool exists_writer(const Interface *interface) const =0
Check if a writer exists for the given interface.
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:62
InterfaceMessageEnqueueException(const char *type, const char *id)
Constructor.
Definition: interface.cpp:74
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:56
InterfaceWriteDeniedException(const char *type, const char *id, const char *msg)
Constructor.
Definition: interface.cpp:54
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
std::list< std::string > readers() const
Get owner names of reading interface instances.
Definition: interface.cpp:895
bool msgq_try_lock()
Try to lock message queue.
Definition: interface.cpp:1119
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
Definition: interface.cpp:1296
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
Definition: interface.h:249
const char * hash_printable() const
Get printable interface hash.
Definition: interface.cpp:314
const void * datachunk() const
Get data chunk.
Definition: interface.cpp:436
void mark_data_changed()
Mark data as changed.
Definition: interface.cpp:778
bool operator==(Interface &comp) const
Check equality of two interfaces.
Definition: interface.cpp:632
void set_validity(bool valid)
Mark this interface invalid.
Definition: interface.cpp:458
unsigned int msgq_enqueue_copy(Message *message)
Enqueue copy of message at end of queue.
Definition: interface.cpp:953
void copy_private_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
Definition: interface.cpp:1322
const char * type() const
Get type of interface.
Definition: interface.cpp:652
bool data_refreshed
Indicator if data can be considered "current", i.e.
Definition: interface.h:246
void set_auto_timestamping(bool enabled)
Enable or disable automated timestamping.
Definition: interface.cpp:755
virtual ~Interface()
Destructor.
Definition: interface.cpp:269
Interface()
Constructor.
Definition: interface.cpp:239
void msgq_pop()
Erase first message from queue.
Definition: interface.cpp:1215
void read_from_buffer(unsigned int buffer)
Copy data from buffer to private memory.
Definition: interface.cpp:1338
std::string writer() const
Get owner name of writing interface instance.
Definition: interface.cpp:886
void * data_ptr
Pointer to local memory storage.
Definition: interface.h:244
const Time * timestamp() const
Get timestamp of last write.
Definition: interface.cpp:714
Message * msgq_first()
Get the first message from the message queue.
Definition: interface.cpp:1200
Time buffer_timestamp(unsigned int buffer)
Get time of a buffer.
Definition: interface.cpp:1379
bool changed() const
Definition: interface.cpp:789
void resize_buffers(unsigned int num_buffers)
Resize buffer array.
Definition: interface.cpp:1261
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: interface.cpp:1240
size_t hash_size() const
Get size of interface hash.
Definition: interface.cpp:426
unsigned int msgq_enqueue(Message *message, bool proxy=false)
Enqueue message at end of queue.
Definition: interface.cpp:915
bool is_writer() const
Check if this is a writing instance.
Definition: interface.cpp:445
void msgq_remove(Message *message)
Remove message from queue.
Definition: interface.cpp:1010
const unsigned char * hash() const
Get interface hash.
Definition: interface.cpp:305
void msgq_append(Message *message)
Enqueue message.
Definition: interface.cpp:986
MessageQueue::MessageIterator msgq_end()
Get end iterator for message queue.
Definition: interface.cpp:1181
unsigned int msgq_size()
Get size of message queue.
Definition: interface.cpp:1045
void write()
Write from local copy into BlackBoard memory.
Definition: interface.cpp:501
const char * id() const
Get identifier of interface.
Definition: interface.cpp:661
void add_fieldinfo(interface_fieldtype_t type, const char *name, size_t length, void *value, const char *enumtype=0, const interface_enum_map_t *enum_map=0)
Add an entry to the field info list.
Definition: interface.cpp:343
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: interface.cpp:1231
void set_hash(unsigned char *ihash)
Set hash.
Definition: interface.cpp:323
bool data_changed
Indicator if the current data is different from the last call to write() This must is automatically u...
Definition: interface.h:247
unsigned int data_size
Minimal data size to hold data storage.
Definition: interface.h:245
unsigned int mem_serial() const
Get memory serial of interface.
Definition: interface.cpp:704
Uuid serial() const
Get instance serial of interface.
Definition: interface.cpp:695
bool msgq_empty()
Check if queue is empty.
Definition: interface.cpp:1062
void set_from_chunk(void *chunk)
Set from a raw data chunk.
Definition: interface.cpp:831
void msgq_lock()
Lock message queue.
Definition: interface.cpp:1098
const char * uid() const
Get unique identifier of interface.
Definition: interface.cpp:686
bool is_valid() const
Check validity of interface.
Definition: interface.cpp:469
void msgq_flush()
Flush all messages.
Definition: interface.cpp:1079
unsigned int num_readers() const
Get the number of readers.
Definition: interface.cpp:876
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:479
int compare_buffers(unsigned int buffer)
Compare buffer to private memory.
Definition: interface.cpp:1360
void msgq_unlock()
Unlock message queue.
Definition: interface.cpp:1137
static void parse_uid(const char *uid, std::string &type, std::string &id)
Parse UID to type and ID strings.
Definition: interface.cpp:1420
void set_clock(Clock *clock)
Set clock to use for timestamping.
Definition: interface.cpp:745
unsigned int num_fields()
Get the number of fields in the interface.
Definition: interface.cpp:1249
unsigned int datasize() const
Get data size.
Definition: interface.cpp:540
std::list< const char * > get_message_types()
Obtain a list of textual representations of the message types available for this interface.
Definition: interface.cpp:408
unsigned int num_buffers() const
Get number of buffers.
Definition: interface.cpp:1287
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:848
void mark_data_refreshed()
Mark data as refreshed.
Definition: interface.cpp:767
void add_messageinfo(const char *name)
Add an entry to the message info list.
Definition: interface.cpp:382
const char * owner() const
Get owner of interface.
Definition: interface.cpp:672
bool oftype(const char *interface_type) const
Check if interface is of given type.
Definition: interface.cpp:643
MessageQueue::MessageIterator msgq_begin()
Get start iterator for message queue.
Definition: interface.cpp:1159
void set_timestamp(const Time *t=NULL)
Set timestamp.
Definition: interface.cpp:724
bool refreshed() const
Check if data has been refreshed.
Definition: interface.cpp:811
virtual bool message_valid(const Message *message) const =0
Check if the message is valid and can be enqueued.
virtual void transmit(Message *message)=0
Transmit message.
Message queue used in interfaces.
Definition: message_queue.h:42
MessageIterator end()
Get iterator to element beyond end of message queue list.
void append(Message *msg)
Append message to queue.
void unlock()
Unlock message queue.
void pop()
Erase first message from queue.
void flush()
Delete all messages from queue.
void lock()
Lock message queue.
void remove(const Message *msg)
Remove message from queue.
bool empty() const
Check if message queue is empty.
MessageIterator begin()
Get iterator to first element in message queue.
bool try_lock()
Try to lock message queue.
unsigned int size() const
Get number of messages in queue.
Message * first()
Get first message from queue.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
void set_id(unsigned int message_id)
Set message ID.
Definition: message.cpp:199
virtual Message * clone() const
Clone this message.
Definition: message.cpp:418
unsigned int id() const
Get message ID.
Definition: message.cpp:181
Mutex locking helper.
Definition: mutex_locker.h:34
Mutex mutual exclusion lock.
Definition: mutex.h:33
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
A NULL pointer was supplied where not allowed.
Definition: software.h:32
Index out of bounds.
Definition: software.h:86
void unlock()
Release the lock.
void lock_for_read()
Aquire a reader lock.
void lock_for_write()
Aquire a writer lock.
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:95
void ref()
Increment reference count.
Definition: refcount.cpp:67
A class for handling time.
Definition: time.h:93
void set_clock(Clock *clock)
Set clock for this instance.
Definition: time.cpp:308
void get_timestamp(long &sec, long &usec) const
Get time stamp.
Definition: time.h:137
Time & stamp()
Set this time to the current time.
Definition: time.cpp:704
void set_time(const timeval *tv)
Sets the time.
Definition: time.cpp:246
A convenience class for universally unique identifiers (UUIDs).
Definition: uuid.h:29
Fawkes library namespace.
std::map< int, std::string > interface_enum_map_t
Map of enum integer to string values.
Definition: types.h:54
interface_fieldtype_t
Interface field type.
Definition: types.h:36
Timestamp data, must be present and first entries for each interface data structs!...
Definition: interface.h:201
int64_t timestamp_usec
additional time microseconds
Definition: interface.h:203
int64_t timestamp_sec
time in seconds since Unix epoch
Definition: interface.h:202
const char * type
the type of the message
Definition: interface.h:194
interface_messageinfo_t * next
the next field, NULL if last
Definition: interface.h:195
Interface field info list.
Definition: types.h:58
const char * enumtype
text representation of enum type
Definition: types.h:60
void * value
Current value of this field.
Definition: types.h:63
size_t length
Length of field (array, string)
Definition: types.h:62
const char * name
Name of this field.
Definition: types.h:61
interface_fieldtype_t type
type of this field
Definition: types.h:59
const interface_enum_map_t * enum_map
Map of possible enum values.
Definition: types.h:64
interface_fieldinfo_t * next
next field, NULL if last
Definition: types.h:65