24 #include <interface/interface.h> 26 #include <interface/mediators/interface_mediator.h> 27 #include <interface/mediators/message_mediator.h> 28 #include <core/threading/refc_rwlock.h> 29 #include <core/threading/mutex.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 data_changed =
false;
245 memset(__hash, 0, __INTERFACE_HASH_SIZE);
246 memset(__hash_printable, 0, __INTERFACE_HASH_SIZE * 2 + 1);
255 __data_mutex =
new Mutex();
262 if ( __rwlock) __rwlock->unref();
264 delete __message_queue;
265 if (__buffers) free(__buffers);
269 __fieldinfo_list = __fieldinfo_list->
next;
271 finfol = __fieldinfo_list;
276 __messageinfo_list = __messageinfo_list->
next;
278 minfol = __messageinfo_list;
281 delete __local_read_timestamp;
291 const unsigned char *
304 return __hash_printable;
314 memcpy(__hash, ihash, __INTERFACE_HASH_SIZE);
315 for (
size_t s = 0; s < __INTERFACE_HASH_SIZE; ++s) {
316 snprintf(&__hash_printable[s*2], 3,
"%02X", __hash[s]);
333 size_t length,
void *value,
const char *enumtype)
339 newinfo->
type = type;
341 newinfo->
name = name;
343 newinfo->
value = value;
344 newinfo->
next = NULL;
346 if ( infol == NULL ) {
348 __fieldinfo_list = newinfo;
351 while ( infol->
next != NULL ) {
354 infol->
next = newinfo;
374 newinfo->
type = type;
375 newinfo->
next = NULL;
377 if ( infol == NULL ) {
379 __messageinfo_list = newinfo;
382 while ( infol->
next != NULL ) {
385 infol->
next = newinfo;
394 std::list<const char *>
397 std::list<const char *> types;
400 while ( cur != NULL ) {
401 types.push_back(cur->
type);
416 return __INTERFACE_HASH_SIZE;
437 return __write_access;
451 __rwlock->lock_for_write();
474 __rwlock->lock_for_read();
475 __data_mutex->lock();
477 memcpy(data_ptr, __mem_data_ptr, data_size);
478 *__local_read_timestamp = *__timestamp;
479 __timestamp->set_time(data_ts->timestamp_sec, data_ts->timestamp_usec);
481 __data_mutex->unlock();
485 __data_mutex->unlock();
497 if ( ! __write_access ) {
501 __rwlock->lock_for_write();
502 __data_mutex->lock();
505 if (__auto_timestamping) __timestamp->stamp();
506 long sec = 0, usec = 0;
507 __timestamp->get_timestamp(sec, usec);
508 data_ts->timestamp_sec = sec;
509 data_ts->timestamp_usec = usec;
510 data_changed =
false;
512 memcpy(__mem_data_ptr, data_ptr, data_size);
514 __data_mutex->unlock();
518 __data_mutex->unlock();
521 __interface_mediator->notify_of_data_change(
this);
541 Interface::set_type_id(
const char *type,
const char *
id)
543 __type[__INTERFACE_TYPE_SIZE] = 0;
544 __id[__INTERFACE_ID_SIZE] = 0;
545 __uid[__INTERFACE_UID_SIZE] = 0;
546 strncpy(__type, type, __INTERFACE_TYPE_SIZE);
547 strncpy(__id,
id, __INTERFACE_ID_SIZE);
548 snprintf(__uid, __INTERFACE_UID_SIZE,
"%s::%s", type,
id);
556 Interface::set_instance_serial(
unsigned short instance_serial)
558 __instance_serial = instance_serial;
570 __interface_mediator = iface_mediator;
571 __message_mediator = msg_mediator;
581 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
583 __mem_serial = serial;
584 __mem_real_ptr = real_ptr;
585 __mem_data_ptr = data_ptr;
594 Interface::set_readwrite(
bool write_access,
RefCountRWLock *rwlock)
596 __write_access = write_access;
615 return ( (strncmp(__type, comp.__type,
sizeof(__type)) == 0) &&
616 (strncmp(__id, comp.__id,
sizeof(__id)) == 0) );
627 return (strncmp(this->__type, interface_type,
sizeof(this->__type)) == 0);
672 return __instance_serial;
704 if (__auto_timestamping)
throw Exception(
"Auto timestamping enabled, cannot " 705 "set explicit timestamp");
706 if (!__write_access)
throw Exception(
"Timestamp can only be set on writing " 712 __timestamp->
stamp();
725 __timestamp->set_clock(clock);
735 __auto_timestamping = enabled;
750 return (*__timestamp != __local_read_timestamp);
772 memcpy(data_ptr, chunk, data_size);
784 return __interface_mediator->exists_writer(
this);
813 return __interface_mediator->num_readers(
this);
832 if ( __write_access ) {
836 if ( message_valid(message) ) {
837 message->set_interface(
this);
838 message->
set_id(next_msg_id());
840 __message_mediator->transmit(message);
841 unsigned int msgid = message->
id();
871 if ( __write_access ) {
874 if ( message == NULL ) {
878 if ( message_valid(message) ) {
880 mcopy->set_interface(
this);
881 mcopy->
set_id(next_msg_id());
882 __message_mediator->transmit(mcopy);
883 unsigned int msgid = mcopy->
id();
901 Interface::msgq_append(
Message *message)
903 if ( ! __write_access ) {
905 "reading instance of an interface (append).");
908 __message_queue->append(message);
925 if ( ! __write_access ) {
927 "reading instance of an interface (remove msg).");
930 return __message_queue->remove(message);
942 if ( ! __write_access ) {
944 "reading instance of an interface (remove id).");
947 return __message_queue->remove(message_id);
958 if ( ! __write_access ) {
960 "reading instance of an interface (size).");
963 return __message_queue->size();
974 if ( ! __write_access ) {
976 "reading instance of an interface (empty).");
979 return __message_queue->empty();
990 if ( ! __write_access ) {
992 "reading instance of an interface (flush).");
995 __message_queue->flush();
1008 if ( ! __write_access ) {
1010 "reading instance of an interface (lock).");
1013 __message_queue->lock();
1028 if ( ! __write_access ) {
1030 "Cannot work on message queue on " 1031 "reading instance of an interface " 1032 "(msgq_try_lock).");
1035 return __message_queue->try_lock();
1046 if ( ! __write_access ) {
1048 "reading instance of an interface (unlock).");
1051 __message_queue->unlock();
1066 if ( ! __write_access ) {
1068 "reading instance of an interface (begin).");
1071 return __message_queue->begin();
1087 if ( ! __write_access ) {
1089 "Cannot work on message queue on " 1090 "reading instance of an interface (end).");
1093 return __message_queue->end();
1106 if ( ! __write_access ) {
1108 "reading instance of an interface (first).");
1111 return __message_queue->first();
1120 if ( ! __write_access ) {
1122 "reading instance of an interface (pop).");
1125 __message_queue->pop();
1155 return __num_fields;
1168 __data_mutex->lock();
1169 if (num_buffers == 0) {
1170 if (__buffers != NULL) {
1176 void *tmp = realloc(__buffers, num_buffers * data_size);
1178 __data_mutex->unlock();
1179 throw Exception(errno,
"Resizing buffers for interface %s failed", __uid);
1182 __num_buffers = num_buffers;
1185 __data_mutex->unlock();
1195 return __num_buffers;
1205 if (buffer >= __num_buffers) {
1207 buffer, 0, __num_buffers);
1211 __rwlock->lock_for_read();
1212 __data_mutex->lock();
1214 void *buf = (
char *)__buffers + buffer * data_size;
1217 memcpy(buf, __mem_data_ptr, data_size);
1219 __data_mutex->unlock();
1223 __data_mutex->unlock();
1234 if (buffer >= __num_buffers) {
1236 buffer, 0, __num_buffers);
1240 __data_mutex->lock();
1241 void *buf = (
char *)__buffers + buffer * data_size;
1242 memcpy(buf, data_ptr, data_size);
1243 __data_mutex->unlock();
1254 if (buffer >= __num_buffers) {
1256 buffer, 0, __num_buffers);
1259 __data_mutex->lock();
1260 void *buf = (
char *)__buffers + buffer * data_size;
1261 memcpy(data_ptr, buf, data_size);
1262 __data_mutex->unlock();
1275 if (buffer >= __num_buffers) {
1277 buffer, 0, __num_buffers);
1280 __data_mutex->lock();
1281 void *buf = (
char *)__buffers + buffer * data_size;
1282 int rv = memcmp(buf, data_ptr, data_size);
1283 __data_mutex->unlock();
1303 #define xstr(s) str(s) 1304 if ((ec = regcomp(&re,
1305 "^([a-zA-Z0-9]{1," xstr(__INTERFACE_TYPE_SIZE)
"})::" 1306 "([a-zA-Z0-9 _\\.-]{1," xstr(__INTERFACE_ID_SIZE)
"})$",
1307 REG_EXTENDED)) != 0) {
1309 regerror(ec, &re, errbuf, 1024);
1310 throw Exception(
"Failed to created regular expression to parse UID (%s)",
1313 regmatch_t matches[3];
1314 if (regexec(&re, uid, 3, matches, 0) != 0) {
1316 throw Exception(
"Failed to match UID %s, format error.", uid);
1319 *type = strndup(&(uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1320 *
id = strndup(&(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.
const char * type
the type of the message
virtual Message * clone() const
Clone this message.
MessageQueue::MessageIterator msgq_begin()
Get start iterator for message queue.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
unsigned short serial() const
Get instance serial of interface.
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.
unsigned int num_readers() const
Get the number of readers.
const char * hash_printable() const
Get printable interface hash.
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.
size_t hash_size() const
Get size of interface hash.
void set_auto_timestamping(bool enabled)
Enable or disable automated timestamping.
Fawkes library namespace.
void msgq_unlock()
Unlock message queue.
bool operator==(Interface &comp) const
Check equality of two interfaces.
const char * name
Name of this field.
interface_messageinfo_t * next
the next field, NULL if last
bool is_valid() const
Check validity of interface.
Exception()
Constructor for subclasses.
This is supposed to be the central clock in Fawkes.
void msgq_remove(Message *message)
Remove message from queue.
interface_fieldinfo_t * next
next field, NULL if last
const unsigned char * hash() const
Get interface hash.
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.
unsigned int id() const
Get message ID.
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.
unsigned int msgq_size()
Get size of message queue.
const char * uid() const
Get unique identifier of interface.
void * value
Current value of this field.
bool has_writer() const
Check if there is a writer for the interface.
unsigned int num_fields()
Get the number of fields in the interface.
const Time * timestamp() const
Get timestamp of last write.
const char * id() const
Get identifier of interface.
void add_messageinfo(const char *name)
Add an entry to the message info list.
void msgq_pop()
Erase first message from queue.
unsigned int datasize() const
Get data size.
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.
static void parse_uid(const char *uid, char **type, char **id)
Parse UID to type and ID strings.
void read()
Read from BlackBoard into local copy.
unsigned int mem_serial() const
Get memory serial of interface.
virtual ~Interface()
Destructor.
Read/write lock with reference counting.
Message queue used in interfaces.
InterfaceInvalidException(const Interface *interface, const char *method)
Constructor.
interface_fieldtype_t type
type of this field
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
unsigned int num_buffers() const
Get number of buffers.
void add_fieldinfo(interface_fieldtype_t type, const char *name, size_t length, void *value, const char *enumtype=0)
Add an entry to the field info list.
size_t length
Length of field (array, string)
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.
bool oftype(const char *interface_type) const
Check if interface is of given type.
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
void msgq_flush()
Flush all messages.
void msgq_lock()
Lock message queue.
int compare_buffers(unsigned int buffer)
Compare buffer to private memory.
void set_validity(bool valid)
Mark this interface invalid.
Time & stamp()
Set this time to the current time.
bool is_writer() const
Check if this is a writing instance.
const void * datachunk() const
Get data chunk.
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.
const char * type() const
Get type of interface.
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.
MessageQueue::MessageIterator msgq_end()
Get end iterator for message queue.