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> 57 :
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.",
94 :
Exception(
"Message of type '%s' cannot be enqueued in interface of type '%s'",
111 :
Exception(
"The interface %s (instance serial %u) is invalid. You cannot call %s anymore.",
235 write_access_ =
false;
238 next_message_id_ = 0;
240 fieldinfo_list_ = NULL;
241 messageinfo_list_ = NULL;
243 timestamp_ =
new Time(0, 0);
244 local_read_timestamp_ =
new Time(0, 0);
245 auto_timestamping_ =
true;
246 owner_ = strdup(
"?");
248 memset(hash_, 0, INTERFACE_HASH_SIZE_);
249 memset(hash_printable_, 0, INTERFACE_HASH_SIZE_ * 2 + 1);
258 data_mutex_ =
new Mutex();
267 delete message_queue_;
273 fieldinfo_list_ = fieldinfo_list_->
next;
275 finfol = fieldinfo_list_;
280 messageinfo_list_ = messageinfo_list_->
next;
282 minfol = messageinfo_list_;
285 delete local_read_timestamp_;
297 const unsigned char *
309 return hash_printable_;
318 memcpy(hash_, ihash, INTERFACE_HASH_SIZE_);
319 for (
size_t s = 0; s < INTERFACE_HASH_SIZE_; ++s) {
320 snprintf(&hash_printable_[s * 2], 3,
"%02X", hash_[s]);
340 const char * enumtype,
348 newinfo->
name = name;
350 newinfo->
value = value;
352 newinfo->
next = NULL;
356 fieldinfo_list_ = newinfo;
359 while (infol->
next != NULL) {
362 infol->
next = newinfo;
382 newinfo->
next = NULL;
386 messageinfo_list_ = newinfo;
389 while (infol->
next != NULL) {
392 infol->
next = newinfo;
400 std::list<const char *>
403 std::list<const char *> types;
406 while (cur != NULL) {
407 types.push_back(cur->
type);
421 return INTERFACE_HASH_SIZE_;
440 return write_access_;
478 *local_read_timestamp_ = *timestamp_;
496 if (!write_access_) {
504 if (auto_timestamping_)
506 long sec = 0, usec = 0;
539 Interface::set_type_id(
const char *type,
const char *
id)
541 strncpy(type_,
type, INTERFACE_TYPE_SIZE_);
542 strncpy(id_,
id, INTERFACE_ID_SIZE_);
543 snprintf(uid_, INTERFACE_UID_SIZE_ + 1,
"%s::%s", type_, id_);
546 type_[INTERFACE_TYPE_SIZE_] = 0;
547 id_[INTERFACE_ID_SIZE_] = 0;
548 uid_[INTERFACE_UID_SIZE_] = 0;
555 Interface::set_instance_serial(
unsigned short instance_serial)
557 instance_serial_ = instance_serial;
565 Interface::set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator)
567 interface_mediator_ = iface_mediator;
568 message_mediator_ = msg_mediator;
577 Interface::set_memory(
unsigned int serial,
void *real_ptr,
void *data_ptr)
580 mem_real_ptr_ = real_ptr;
589 Interface::set_readwrite(
bool write_access, RefCountRWLock *rwlock)
591 write_access_ = write_access;
599 Interface::set_owner(
const char *owner)
605 owner_ = strdup(
owner);
622 return ((strncmp(type_, comp.type_,
sizeof(type_)) == 0)
623 && (strncmp(id_, comp.id_,
sizeof(id_)) == 0));
633 return (strncmp(this->type_, interface_type,
sizeof(this->type_)) == 0);
685 return instance_serial_;
714 if (auto_timestamping_)
715 throw Exception(
"Auto timestamping enabled, cannot " 716 "set explicit timestamp");
718 throw Exception(
"Timestamp can only be set on writing " 745 auto_timestamping_ = enabled;
782 return (*timestamp_ != local_read_timestamp_);
854 return interface_mediator_->
writer(
this);
860 std::list<std::string>
863 return interface_mediator_->
readers(
this);
886 message->set_interface(
this);
887 message->
set_id(next_msg_id());
889 message_mediator_->
transmit(message);
890 unsigned int msgid = message->
id();
922 if (message == NULL) {
928 mcopy->set_interface(
this);
929 mcopy->
set_id(next_msg_id());
931 unsigned int msgid = mcopy->
id();
952 if (!write_access_) {
955 "Cannot work on message queue on " 956 "reading instance of an interface (append).");
960 message_queue_->
append(message);
976 if (!write_access_) {
979 "Cannot work on message queue on " 980 "reading instance of an interface (remove msg).");
983 return message_queue_->
remove(message);
994 if (!write_access_) {
997 "Cannot work on message queue on " 998 "reading instance of an interface (remove id).");
1001 return message_queue_->
remove(message_id);
1011 if (!write_access_) {
1014 "Cannot work on message queue on " 1015 "reading instance of an interface (size).");
1018 return message_queue_->
size();
1028 if (!write_access_) {
1031 "Cannot work on message queue on " 1032 "reading instance of an interface (empty).");
1035 return message_queue_->
empty();
1045 if (!write_access_) {
1048 "Cannot work on message queue on " 1049 "reading instance of an interface (flush).");
1052 message_queue_->
flush();
1064 if (!write_access_) {
1067 "Cannot work on message queue on " 1068 "reading instance of an interface (lock).");
1071 message_queue_->
lock();
1085 if (!write_access_) {
1088 "Cannot work on message queue on " 1089 "reading instance of an interface " 1090 "(msgq_try_lock).");
1103 if (!write_access_) {
1106 "Cannot work on message queue on " 1107 "reading instance of an interface (unlock).");
1110 message_queue_->
unlock();
1125 if (!write_access_) {
1128 "Cannot work on message queue on " 1129 "reading instance of an interface (begin).");
1132 return message_queue_->
begin();
1147 if (!write_access_) {
1150 "Cannot work on message queue on " 1151 "reading instance of an interface (end).");
1154 return message_queue_->
end();
1166 if (!write_access_) {
1169 "Cannot work on message queue on " 1170 "reading instance of an interface (first).");
1172 return message_queue_->
first();
1181 if (!write_access_) {
1184 "Cannot work on message queue on " 1185 "reading instance of an interface (pop).");
1188 message_queue_->
pop();
1227 data_mutex_->
lock();
1229 if (buffers_ != NULL) {
1238 throw Exception(errno,
"Resizing buffers for interface %s failed", uid_);
1253 return num_buffers_;
1262 if (buffer >= num_buffers_) {
1267 data_mutex_->
lock();
1269 void *buf = (
char *)buffers_ + buffer *
data_size;
1288 if (buffer >= num_buffers_) {
1292 data_mutex_->
lock();
1293 void *buf = (
char *)buffers_ + buffer *
data_size;
1304 if (buffer >= num_buffers_) {
1308 data_mutex_->
lock();
1309 void *buf = (
char *)buffers_ + buffer *
data_size;
1311 *local_read_timestamp_ = *timestamp_;
1326 if (buffer >= num_buffers_) {
1330 data_mutex_->
lock();
1331 void *buf = (
char *)buffers_ + buffer *
data_size;
1345 if (buffer >= num_buffers_) {
1350 void * buf = (
char *)buffers_ + buffer *
data_size;
1363 if (buffer >= num_buffers_) {
1371 void * buf = (
char *)buffers_ + buffer *
data_size;
1390 #define xstr(s) str(s) 1391 if ((ec = regcomp(&re,
1392 "^([a-zA-Z0-9]{1," xstr(INTERFACE_TYPE_SIZE_)
"})::" 1393 "([a-zA-Z0-9 _/\\.-]{1," xstr(
1394 INTERFACE_ID_SIZE_)
"})$",
1398 regerror(ec, &re, errbuf, 1024);
1399 throw Exception(
"Failed to created regular expression to parse UID (%s)", errbuf);
1401 regmatch_t matches[3];
1402 if (regexec(&re,
uid, 3, matches, 0) != 0) {
1404 throw Exception(
"Failed to match UID %s, format error.",
uid);
1407 type.assign(&(
uid[matches[1].rm_so]), matches[1].rm_eo - matches[1].rm_so);
1408 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.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
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 get_timestamp(long &sec, long &usec) const
Get time stamp.
void lock_for_read()
Aquire a reader lock.
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.
MessageIterator end()
Get iterator to element beyond end of message queue list.
Fawkes library namespace.
void msgq_unlock()
Unlock message queue.
void unlock()
Unlock the mutex.
const char * name
Name of this field.
interface_messageinfo_t * next
the next field, NULL if last
unsigned int data_size
Minimal data size to hold data storage.
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 lock_for_write()
Aquire a writer lock.
void add_messageinfo(const char *name)
Add an entry to the message info list.
void msgq_pop()
Erase first message from queue.
bool data_changed
Indicator if data has changed.
const char * type() const
Get type of interface.
void * data_ptr
Pointer to local memory storage.
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.
void set_clock(Clock *clock)
Set clock for this instance.
virtual bool message_valid(const Message *message) const =0
Check if the message is valid and can be enqueued.
unsigned short serial() const
Get instance serial of interface.
void read()
Read from BlackBoard into local copy.
void flush()
Delete all messages from queue.
virtual ~Interface()
Destructor.
int64_t timestamp_usec
additional time microseconds
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!...
void copy_shared_to_buffer(unsigned int buffer)
Copy data from private memory to buffer.
unsigned int size() const
Get number of messages in queue.
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.
bool try_lock()
Try to lock message queue.
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.
MessageIterator begin()
Get iterator to first element in message 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 append(Message *msg)
Append message to queue.
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.
bool empty() const
Check if message queue is empty.
void lock()
Lock this mutex.
Time & stamp()
Set this time to the current time.
void remove(const Message *msg)
Remove message from queue.
const void * datachunk() const
Get data chunk.
void unlock()
Release the lock.
void pop()
Erase first message from queue.
unsigned int num_readers() const
Get the number of readers.
void unlock()
Unlock message queue.
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Message * first()
Get first message from queue.
Mutex mutual exclusion lock.
void set_from_chunk(void *chunk)
Set from a raw data chunk.
void lock()
Lock message queue.
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.