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
41namespace 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 */
304const unsigned char *
306{
307 return hash_;
308}
309
310/** Get printable interface hash.
311 * @return printable version of hash()
312 */
313const char *
315{
316 return hash_printable_;
317}
318
319/** Set hash. Never use directly.
320 * @param ihash interface hash
321 */
322void
323Interface::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 */
342void
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 */
381void
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 */
407std::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 */
425size_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 */
435const 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 */
444bool
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 */
457void
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 */
468bool
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 */
478void
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 */
500void
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 */
539unsigned 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 */
550void
551Interface::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 */
566void
567Interface::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 */
576void
577Interface::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 */
588void
589Interface::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 */
600void
601Interface::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 */
610void
611Interface::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 */
631bool
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 */
642bool
643Interface::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 */
651const char *
653{
654 return type_;
655}
656
657/** Get identifier of interface.
658 * @return string with the identifier of the interface.
659 */
660const 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 */
671const 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 */
685const char *
687{
688 return uid_;
689}
690
691/** Get instance serial of interface.
692 * @return instance serial of the interface.
693 */
694Uuid
696{
697 return instance_serial_;
698}
699
700/** Get memory serial of interface.
701 * @return memory serial of interface
702 */
703unsigned 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 */
713const 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 */
723void
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 */
744void
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 */
754void
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 */
766void
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 */
777void
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 */
788bool
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 */
810bool
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 */
830void
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 */
847bool
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 */
875unsigned 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 */
885std::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 */
894std::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 */
914unsigned int
915Interface::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 */
952unsigned 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 */
985void
987{
988 if (!write_access_) {
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 */
1009void
1011{
1012 if (!write_access_) {
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 */
1027void
1028Interface::msgq_remove(unsigned int message_id)
1029{
1030 if (!write_access_) {
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 */
1044unsigned int
1046{
1047 if (!write_access_) {
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 */
1061bool
1063{
1064 if (!write_access_) {
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 */
1078void
1080{
1081 if (!write_access_) {
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 */
1097void
1099{
1100 if (!write_access_) {
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 */
1118bool
1120{
1121 if (!write_access_) {
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 */
1136void
1138{
1139 if (!write_access_) {
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_) {
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_) {
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 */
1199Message *
1201{
1202 if (!write_access_) {
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 */
1214void
1216{
1217 if (!write_access_) {
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 */
1248unsigned 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 */
1260void
1261Interface::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 */
1286unsigned 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 */
1295void
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 */
1321void
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 */
1337void
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 */
1359int
1360Interface::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 */
1378Time
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;
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 */
1396void
1397Interface::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;
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 */
1419void
1420Interface::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