23 #include <interface/interface.h> 25 #include <interface/mediators/interface_mediator.h> 26 #include <interface/mediators/message_mediator.h> 27 #include <core/threading/refc_rwlock.h> 28 #include <core/threading/mutex.h> 29 #include <core/threading/mutex_locker.h> 30 #include <core/exceptions/system.h> 31 #include <utils/time/clock.h> 32 #include <utils/time/time.h> 33 #include <utils/misc/strndup.h> 58 :
Exception(
"This interface instance '%s' of type '%s' is not opened for writing. %s",
75 :
Exception(
"This interface instance '%s' of type '%s' IS opened for writing, but " 76 "messages can only be enqueued on reading interfaces.", id, type)
92 :
Exception(
"Message of type '%s' cannot be enqueued in interface of type '%s'",
93 message->type(), interface->type())
110 :
Exception(
"The interface %s (instance serial %u) is invalid. You cannot call %s anymore.",
111 interface->uid(), interface->serial(), method)
233 __write_access =
false;
236 __next_message_id = 0;
238 __fieldinfo_list = NULL;
239 __messageinfo_list = NULL;
241 __timestamp =
new Time(0, 0);
242 __local_read_timestamp =
new Time(0, 0);
243 __auto_timestamping =
true;
244 __owner = strdup(
"?");
245 data_changed =
false;
246 memset(__hash, 0, __INTERFACE_HASH_SIZE);
247 memset(__hash_printable, 0, __INTERFACE_HASH_SIZE * 2 + 1);
256 __data_mutex =
new Mutex();
263 if ( __rwlock) __rwlock->unref();
265 delete __message_queue;
266 if (__buffers) free(__buffers);
270 __fieldinfo_list = __fieldinfo_list->
next;
272 finfol = __fieldinfo_list;
277 __messageinfo_list = __messageinfo_list->
next;
279 minfol = __messageinfo_list;
282 delete __local_read_timestamp;
283 if (__owner) free(__owner);
293 const unsigned char *
306 return __hash_printable;
316 memcpy(__hash, ihash, __INTERFACE_HASH_SIZE);
317 for (
size_t s = 0; s < __INTERFACE_HASH_SIZE; ++s) {
318 snprintf(&__hash_printable[s*2], 3,
"%02X", __hash[s]);
336 size_t length,
void *value,
const char *enumtype,
343 newinfo->
type = type;
345 newinfo->
name = name;
347 newinfo->
value = value;
349 newinfo->
next = NULL;
351 if ( infol == NULL ) {
353 __fieldinfo_list = newinfo;
356 while ( infol->
next != NULL ) {
359 infol->
next = newinfo;
379 newinfo->
type = type;
380 newinfo->
next = NULL;
382 if ( infol == NULL ) {
384 __messageinfo_list = newinfo;
387 while ( infol->
next != NULL ) {
390 infol->
next = newinfo;
399 std::list<const char *>
402 std::list<const char *> types;
405 while ( cur != NULL ) {
406 types.push_back(cur->
type);
421 return __INTERFACE_HASH_SIZE;
442 return __write_access;
456 __rwlock->lock_for_write();
479 __rwlock->lock_for_read();
480 __data_mutex->lock();
482 memcpy(data_ptr, __mem_data_ptr, data_size);
483 *__local_read_timestamp = *__timestamp;
484 __timestamp->set_time(data_ts->timestamp_sec, data_ts->timestamp_usec);
486 __data_mutex->unlock();
490 __data_mutex->unlock();
502 if ( ! __write_access ) {
506 __rwlock->lock_for_write();
507 __data_mutex->lock();
510 if (__auto_timestamping) __timestamp->stamp();
511 long sec = 0, usec = 0;
512 __timestamp->get_timestamp(sec, usec);
513 data_ts->timestamp_sec = sec;
514 data_ts->timestamp_usec = usec;
515 data_changed =
false;
517 memcpy(__mem_data_ptr, data_ptr, data_size);
519 __data_mutex->unlock();
523 __data_mutex->unlock();
526 __interface_mediator->notify_of_data_change(
this);
546 Interface::set_type_id(
const char *type,
const char *
id)
548 __type[__INTERFACE_TYPE_SIZE] = 0;
549 __id[__INTERFACE_ID_SIZE] = 0;
550 __uid[__INTERFACE_UID_SIZE] = 0;
551 strncpy(__type, type, __INTERFACE_TYPE_SIZE);
552 strncpy(__id,
id, __INTERFACE_ID_SIZE);
553 snprintf(__uid, __INTERFACE_UID_SIZE,
"%s::%s", __type, __id);
561 Interface::set_instance_serial(
unsigned short instance_serial)
563 __instance_serial = instance_serial;
575 __interface_mediator = iface_mediator;
576 __message_mediator = msg_mediator;
586 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
588 __mem_serial = serial;
589 __mem_real_ptr = real_ptr;
590 __mem_data_ptr = data_ptr;
599 Interface::set_readwrite(
bool write_access,
RefCountRWLock *rwlock)
601 __write_access = write_access;
610 Interface::set_owner(
const char *owner)
612 if (__owner) free(__owner);
614 if (owner) __owner = strdup(owner);
631 return ( (strncmp(__type, comp.__type,
sizeof(__type)) == 0) &&
632 (strncmp(__id, comp.__id,
sizeof(__id)) == 0) );
643 return (strncmp(this->__type, interface_type,
sizeof(this->__type)) == 0);
699 return __instance_serial;
731 if (__auto_timestamping)
throw Exception(
"Auto timestamping enabled, cannot " 732 "set explicit timestamp");
733 if (!__write_access)
throw Exception(
"Timestamp can only be set on writing " 739 __timestamp->
stamp();
752 __timestamp->set_clock(clock);
762 __auto_timestamping = enabled;
798 if (__write_access) {
801 return (*__timestamp != __local_read_timestamp);
824 memcpy(data_ptr, chunk, data_size);
836 return __interface_mediator->exists_writer(
this);
865 return __interface_mediator->num_readers(
this);
876 return __interface_mediator->writer(
this);
883 std::list<std::string>
886 return __interface_mediator->readers(
this);
905 if ( __write_access ) {
909 if ( message_valid(message) ) {
910 message->set_interface(
this);
911 message->
set_id(next_msg_id());
913 __message_mediator->transmit(message);
914 unsigned int msgid = message->
id();
944 if ( __write_access ) {
947 if ( message == NULL ) {
951 if ( message_valid(message) ) {
953 mcopy->set_interface(
this);
954 mcopy->
set_id(next_msg_id());
955 __message_mediator->transmit(mcopy);
956 unsigned int msgid = mcopy->
id();
978 if ( ! __write_access ) {
980 "reading instance of an interface (append).");
984 __message_queue->append(message);
1001 if ( ! __write_access ) {
1003 "reading instance of an interface (remove msg).");
1006 return __message_queue->remove(message);
1018 if ( ! __write_access ) {
1020 "reading instance of an interface (remove id).");
1023 return __message_queue->remove(message_id);
1034 if ( ! __write_access ) {
1036 "reading instance of an interface (size).");
1039 return __message_queue->size();
1050 if ( ! __write_access ) {
1052 "reading instance of an interface (empty).");
1055 return __message_queue->empty();
1066 if ( ! __write_access ) {
1068 "reading instance of an interface (flush).");
1071 __message_queue->flush();
1084 if ( ! __write_access ) {
1086 "reading instance of an interface (lock).");
1089 __message_queue->lock();
1104 if ( ! __write_access ) {
1106 "Cannot work on message queue on " 1107 "reading instance of an interface " 1108 "(msgq_try_lock).");
1111 return __message_queue->try_lock();
1122 if ( ! __write_access ) {
1124 "reading instance of an interface (unlock).");
1127 __message_queue->unlock();
1142 if ( ! __write_access ) {
1144 "reading instance of an interface (begin).");
1147 return __message_queue->begin();
1163 if ( ! __write_access ) {
1165 "Cannot work on message queue on " 1166 "reading instance of an interface (end).");
1169 return __message_queue->end();
1182 if ( ! __write_access ) {
1184 "reading instance of an interface (first).");
1186 return __message_queue->first();
1195 if ( ! __write_access ) {
1197 "reading instance of an interface (pop).");
1200 __message_queue->pop();
1230 return __num_fields;
1243 __data_mutex->lock();
1244 if (num_buffers == 0) {
1245 if (__buffers != NULL) {
1251 void *tmp = realloc(__buffers, num_buffers * data_size);
1253 __data_mutex->unlock();
1254 throw Exception(errno,
"Resizing buffers for interface %s failed", __uid);
1257 __num_buffers = num_buffers;
1260 __data_mutex->unlock();
1270 return __num_buffers;
1280 if (buffer >= __num_buffers) {
1282 buffer, 0, __num_buffers);
1286 __rwlock->lock_for_read();
1287 __data_mutex->lock();
1289 void *buf = (
char *)__buffers + buffer * data_size;
1292 memcpy(buf, __mem_data_ptr, data_size);
1294 __data_mutex->unlock();
1298 __data_mutex->unlock();
1309 if (buffer >= __num_buffers) {
1311 buffer, 0, __num_buffers);
1315 __data_mutex->lock();
1316 void *buf = (
char *)__buffers + buffer * data_size;
1317 memcpy(buf, data_ptr, data_size);
1318 __data_mutex->unlock();
1329 if (buffer >= __num_buffers) {
1331 buffer, 0, __num_buffers);
1334 __data_mutex->lock();
1335 void *buf = (
char *)__buffers + buffer * data_size;
1336 memcpy(data_ptr, buf, data_size);
1337 *__local_read_timestamp = *__timestamp;
1338 __timestamp->set_time(data_ts->timestamp_sec, data_ts->timestamp_usec);
1340 __data_mutex->unlock();
1353 if (buffer >= __num_buffers) {
1355 buffer, 0, __num_buffers);
1358 __data_mutex->lock();
1359 void *buf = (
char *)__buffers + buffer * data_size;
1360 int rv = memcmp(buf, data_ptr, data_size);
1361 __data_mutex->unlock();
1374 if (buffer >= __num_buffers) {
1376 buffer, 0, __num_buffers);
1381 void *buf = (
char *)__buffers + buffer * data_size;
1395 if (buffer >= __num_buffers) {
1397 buffer, 0, __num_buffers);
1399 if (timestamp == NULL) {
1404 void *buf = (
char *)__buffers + buffer * data_size;
1424 #define xstr(s) str(s) 1425 if ((ec = regcomp(&re,
1426 "^([a-zA-Z0-9]{1," xstr(__INTERFACE_TYPE_SIZE)
"})::" 1427 "([a-zA-Z0-9 _/\\.-]{1," xstr(__INTERFACE_ID_SIZE)
"})$",
1428 REG_EXTENDED)) != 0) {
1430 regerror(ec, &re, errbuf, 1024);
1431 throw Exception(
"Failed to created regular expression to parse UID (%s)",
1434 regmatch_t matches[3];
1435 if (regexec(&re, uid, 3, matches, 0) != 0) {
1437 throw Exception(
"Failed to match UID %s, format error.", uid);
1440 type.assign(&(uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1441 id.assign(&(uid[matches[2].rm_so]), matches[2].rm_eo - matches[2].rm_so);
void copy_private_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
Interface field iterator.
int64_t timestamp_sec
time in seconds since Unix epoch
const char * owner() const
Get owner of interface.
bool operator==(Interface &comp) const
Check equality of two interfaces.
const char * type
the type of the message
std::string writer() const
Get owner name of writing interface instance.
MessageQueue::MessageIterator msgq_begin()
Get start iterator for message queue.
unsigned int datasize() const
Get data size.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
unsigned int id() const
Get message ID.
static Clock * instance()
Clock initializer.
This exception is thrown if a write has been attempted on a read-only interface.
bool msgq_empty()
Check if queue is empty.
InterfaceInvalidMessageException(const Interface *interface, const Message *message)
Constructor.
void unref()
Decrement reference count and conditionally delete this instance.
void set_hash(unsigned char *ihash)
Set hash.
Interface field info list.
unsigned int msgq_enqueue_copy(Message *message)
Enqueue copy of message at end of queue.
void set_auto_timestamping(bool enabled)
Enable or disable automated timestamping.
Fawkes library namespace.
void msgq_unlock()
Unlock message queue.
const char * name
Name of this field.
interface_messageinfo_t * next
the next field, NULL if last
Exception()
Constructor for subclasses.
This is supposed to be the central clock in Fawkes.
void msgq_remove(Message *message)
Remove message from queue.
const char * id() const
Get identifier of interface.
interface_fieldinfo_t * next
next field, NULL if last
A class for handling time.
A NULL pointer was supplied where not allowed.
InterfaceMessageEnqueueException(const char *type, const char *id)
Constructor.
void write()
Write from local copy into BlackBoard memory.
void msgq_append(Message *message)
Enqueue message.
Base class for all Fawkes BlackBoard interfaces.
This exception is thrown if a message has been queued in the interface which is not recognized by the...
bool msgq_try_lock()
Try to lock message queue.
bool is_valid() const
Check validity of interface.
unsigned int msgq_size()
Get size of message queue.
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.
void * value
Current value of this field.
Time buffer_timestamp(unsigned int buffer)
Get time of a buffer.
unsigned int num_fields()
Get the number of fields in the interface.
unsigned int mem_serial() const
Get memory serial of interface.
const unsigned char * hash() const
Get interface hash.
const interface_enum_map_t * enum_map
Map of possible enum values.
void add_messageinfo(const char *name)
Add an entry to the message info list.
void msgq_pop()
Erase first message from queue.
const char * type() const
Get type of interface.
void read_from_buffer(unsigned int buffer)
Copy data from buffer to private memory.
Base class for exceptions in Fawkes.
Message * msgq_first()
Get the first message from the message queue.
InterfaceWriteDeniedException(const char *type, const char *id, const char *msg)
Constructor.
unsigned short serial() const
Get instance serial of interface.
void read()
Read from BlackBoard into local copy.
virtual ~Interface()
Destructor.
int64_t timestamp_usec
additional time microseconds
Read/write lock with reference counting.
void ref()
Increment reference count.
Message queue used in interfaces.
InterfaceInvalidException(const Interface *interface, const char *method)
Constructor.
interface_fieldtype_t type
type of this field
bool has_writer() const
Check if there is a writer for the interface.
Timestamp data, must be present and first entries for each interface data structs! This leans on time...
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
const char * uid() const
Get unique identifier of interface.
bool oftype(const char *interface_type) const
Check if interface is of given type.
size_t hash_size() const
Get size of interface hash.
size_t length
Length of field (array, string)
const Time * timestamp() const
Get timestamp of last write.
bool is_writer() const
Check if this is a writing instance.
bool changed() const
Check if data has been changed.
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
InterfaceFieldIterator fields_end()
Invalid iterator.
void set_time(const timeval *tv)
Sets the time.
void set_clock(Clock *clock)
Set clock to use for timestamping.
void resize_buffers(unsigned int num_buffers)
Resize buffer array.
const char * enumtype
text representation of enum type
static void parse_uid(const char *uid, std::string &type, std::string &id)
Parse UID to type and ID strings.
void msgq_flush()
Flush all messages.
void msgq_lock()
Lock message queue.
int compare_buffers(unsigned int buffer)
Compare buffer to private memory.
unsigned int num_buffers() const
Get number of buffers.
void set_validity(bool valid)
Mark this interface invalid.
Time & stamp()
Set this time to the current time.
const void * datachunk() const
Get data chunk.
unsigned int num_readers() const
Get the number of readers.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Mutex mutual exclusion lock.
void set_from_chunk(void *chunk)
Set from a raw data chunk.
This exception is thrown if a write has been attempted on a read-only interface.
interface_fieldtype_t
Interface field type.
std::list< std::string > readers() const
Get owner names of reading interface instances.
std::map< int, std::string > interface_enum_map_t
Map of enum integer to string values.
void set_timestamp(const Time *t=NULL)
Set timestamp.
std::list< const char * > get_message_types()
Obtain a list of textual representations of the message types available for this interface.
void set_id(unsigned int message_id)
Set message ID.
virtual Message * clone() const
Clone this message.
void mark_data_changed()
Mark data as changed.
const char * hash_printable() const
Get printable interface hash.
MessageQueue::MessageIterator msgq_end()
Get end iterator for message queue.