Fawkes API Fawkes Development Version
interface.h
1
2/***************************************************************************
3 * interface.h - BlackBoard Interface
4 *
5 * Created: Mon Oct 09 18:34:11 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#ifndef _INTERFACE_H_
24#define _INTERFACE_H_
25
26#include <core/exception.h>
27#include <interface/message.h>
28#include <interface/message_queue.h>
29#include <utils/uuid.h>
30
31#include <cstddef>
32#include <list>
33#include <stdint.h>
34
35#define INTERFACE_TYPE_SIZE_ 48
36#define INTERFACE_ID_SIZE_ 64
37// We use MD5 as interface hash
38#define INTERFACE_HASH_SIZE_ 16
39// UID is: type :: id
40#define INTERFACE_UID_SIZE_ INTERFACE_TYPE_SIZE_ + 2 + INTERFACE_ID_SIZE_
41
42namespace fawkes {
43
44class RefCountRWLock;
45class InterfaceMediator;
46class MessageMediator;
47class Time;
48class Clock;
49class Mutex;
50class BlackBoardInterfaceManager;
51class BlackBoardInstanceFactory;
52class BlackBoardMessageManager;
53class BlackBoardInterfaceProxy;
54
56{
57public:
58 InterfaceWriteDeniedException(const char *type, const char *id, const char *msg);
59};
60
62{
63public:
64 InterfaceMessageEnqueueException(const char *type, const char *id);
65};
66
68{
69public:
70 InterfaceInvalidMessageException(const Interface *interface, const Message *message);
71};
72
74{
75public:
76 InterfaceInvalidException(const Interface *interface, const char *method);
77};
78
80{
85
86public:
87 virtual ~Interface();
88
89 bool oftype(const char *interface_type) const;
90 const void * datachunk() const;
91 unsigned int datasize() const;
92 const char * type() const;
93 const char * id() const;
94 const char * uid() const;
95 Uuid serial() const;
96 unsigned int mem_serial() const;
97 bool operator==(Interface &comp) const;
98 const unsigned char *hash() const;
99 size_t hash_size() const;
100 const char * hash_printable() const;
101 bool is_writer() const;
102 void set_validity(bool valid);
103 bool is_valid() const;
104 const char * owner() const;
105
106 void set_from_chunk(void *chunk);
107
108 virtual Message * create_message(const char *type) const = 0;
109 virtual void copy_values(const Interface *interface) = 0;
110 virtual const char *enum_tostring(const char *enumtype, int val) const = 0;
111
112 void resize_buffers(unsigned int num_buffers);
113 unsigned int num_buffers() const;
114 void copy_shared_to_buffer(unsigned int buffer);
115 void copy_private_to_buffer(unsigned int buffer);
116 void read_from_buffer(unsigned int buffer);
117 int compare_buffers(unsigned int buffer);
118 Time buffer_timestamp(unsigned int buffer);
119 void buffer_timestamp(unsigned int buffer, Time *timestamp);
120
121 void read();
122 void write();
123
124 bool has_writer() const;
125 unsigned int num_readers() const;
126 std::string writer() const;
127 std::list<std::string> readers() const;
128
129 bool changed() const;
130 bool refreshed() const;
131 const Time *timestamp() const;
132 void set_auto_timestamping(bool enabled);
133 void set_timestamp(const Time *t = NULL);
134 void set_clock(Clock *clock);
135 void mark_data_refreshed();
136 void mark_data_changed();
137
138 std::list<const char *> get_message_types();
139
140 unsigned int msgq_enqueue(Message *message, bool proxy = false);
141 unsigned int msgq_enqueue_copy(Message *message);
142 void msgq_remove(Message *message);
143 void msgq_remove(unsigned int message_id);
144 unsigned int msgq_size();
145 void msgq_flush();
146 void msgq_lock();
147 bool msgq_try_lock();
148 void msgq_unlock();
149 void msgq_pop();
151 bool msgq_empty();
152 void msgq_append(Message *message);
153
154 /** Check if first message has desired type.
155 * @return true, if message has desired type, false otherwise
156 */
157 template <class MessageType>
158 bool msgq_first_is();
159
160 /** Get first message casted to the desired type.
161 * @return message casted to desired type
162 * @exception TypeMismatchException thrown if message is not of desired type
163 */
164 template <class MessageType>
165 MessageType *msgq_first();
166
167 /** Get first message casted to the desired type.
168 * @param msg reference to pointer to message of desired type, upon successful
169 * return points to the message.
170 * @return message casted to desired type (same as msg parameter)
171 * @exception TypeMismatchException thrown if message is not of desired type
172 */
173 template <class MessageType>
174 MessageType *msgq_first(MessageType *&msg);
175
176 /** Get first message casted to the desired type without exceptions.
177 * This method allows to combine a call to msgq_first_is() and msgq_first()
178 * into a single call.
179 * @param msg reference to pointer to message of desired type, upon successful
180 * return points to the message.
181 * @return pointer to message if it is of the desired type, 0 otherwise
182 */
183 template <class MessageType>
184 MessageType *msgq_first_safe(MessageType *&msg) noexcept;
185
188
189 /* Introspection */
190
191 /** Message info list */
193 {
194 const char * type; /**< the type of the message */
195 interface_messageinfo_t *next; /**< the next field, NULL if last */
196 };
197
198 /** Timestamp data, must be present and first entries for each interface
199 * data structs! This leans on timeval struct. */
200 typedef struct
201 {
202 int64_t timestamp_sec; /**< time in seconds since Unix epoch */
203 int64_t timestamp_usec; /**< additional time microseconds */
205
208
209 unsigned int num_fields();
210
211 /* Convenience */
212 static void parse_uid(const char *uid, std::string &type, std::string &id);
213
214protected:
215 Interface();
216 virtual bool message_valid(const Message *message) const = 0;
217
218 void set_hash(unsigned char *ihash);
220 const char * name,
221 size_t length,
222 void * value,
223 const char * enumtype = 0,
224 const interface_enum_map_t *enum_map = 0);
225 void add_messageinfo(const char *name);
226
227 /** Set a field, set @ref data_changed to true and update
228 * @ref data_changed accordingly
229 * @param field Reference to the field
230 * @param data New field value
231 */
232 template <class FieldT, class DataT>
233 void set_field(FieldT &field, DataT &data);
234
235 /** Set an array field at a given index, set @ref data_changed to true
236 * and update @ref data_changed accordingly
237 * @param field Reference to the array field
238 * @param index Index into the array field
239 * @param data New value to put at given index
240 */
241 template <class FieldT, class DataT>
242 void set_field(FieldT &field, unsigned int index, DataT &data);
243
244 void * data_ptr;
245 unsigned int data_size;
248
250
251private:
252 void set_type_id(const char *type, const char *id);
253 void set_instance_serial(const Uuid &serial);
254 void set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator);
255 void set_memory(unsigned int serial, void *real_ptr, void *data_ptr);
256 void set_readwrite(bool write_access, RefCountRWLock *rwlock);
257 void set_owner(const char *owner);
258
259 inline unsigned int
260 next_msg_id()
261 {
262 return ++next_message_id_;
263 }
264
265 char type_[INTERFACE_TYPE_SIZE_ + 1];
266 char id_[INTERFACE_ID_SIZE_ + 1];
267 char uid_[INTERFACE_UID_SIZE_ + 1];
268 unsigned char hash_[INTERFACE_HASH_SIZE_];
269 char hash_printable_[INTERFACE_HASH_SIZE_ * 2 + 1];
270 char * owner_;
271
272 Uuid instance_serial_;
273 bool valid_;
274
275 void * mem_data_ptr_;
276 void * mem_real_ptr_;
277 unsigned int mem_serial_;
278 bool write_access_;
279
280 void * buffers_;
281 unsigned int num_buffers_;
282
283 Mutex * data_mutex_;
284 RefCountRWLock *rwlock_;
285
286 InterfaceMediator *interface_mediator_;
287 MessageMediator * message_mediator_;
288 MessageQueue * message_queue_;
289 unsigned short next_message_id_;
290
291 interface_fieldinfo_t * fieldinfo_list_;
292 interface_messageinfo_t *messageinfo_list_;
293
294 unsigned int num_fields_;
295
296 Clock *clock_;
297 Time * timestamp_;
298 Time * local_read_timestamp_;
299 bool auto_timestamping_;
300};
301
302template <class FieldT, class DataT>
303void
304Interface::set_field(FieldT &field, DataT &data)
305{
306 data_changed |= change_field(field, data);
307 data_refreshed = true;
308}
309
310template <class FieldT, class DataT>
311void
312Interface::set_field(FieldT &field, unsigned int index, DataT &data)
313{
314 data_changed |= change_field(field, index, data);
315 data_refreshed = true;
316}
317
318template <class MessageType>
319MessageType *
321{
322 MessageType *m = dynamic_cast<MessageType *>(message_queue_->first());
323 if (m) {
324 return m;
325 } else {
326 throw TypeMismatchException("Message is not of desired type");
327 }
328}
329
330template <class MessageType>
331MessageType *
332Interface::msgq_first(MessageType *&msg)
333{
334 msg = this->msgq_first<MessageType>();
335 return msg;
336}
337
338template <class MessageType>
339MessageType *
340Interface::msgq_first_safe(MessageType *&msg) noexcept
341{
342 msg = dynamic_cast<MessageType *>(message_queue_->first());
343 return msg;
344}
345
346/** Check if first message has desired type.
347 * @return true, if message has desired type, false otherwise
348 */
349template <class MessageType>
350bool
352{
353 return (dynamic_cast<MessageType *>(message_queue_->first()) != 0);
354}
355
356/** Interface destructor function for the shared library.
357 * Do not use directly. Use EXPORT_INTERFACE macro.
358 * @param interface Interface to destroy
359 */
360typedef void (*InterfaceDestroyFunc)(Interface *interface);
361
362/** Interface generator function for the shared library
363 * Do not use directly. Use EXPORT_INTERFACE macro.
364 */
365typedef Interface *(*InterfaceFactoryFunc)(void);
366
367/** Friend for interface generator function. */
368#define INTERFACE_MGMT_FRIENDS(interface_class) \
369 friend Interface *private_new##interface_class(); \
370 friend void private_delete##interface_class(interface_class *interface);
371
372/** Interface generator function for this plugin.
373 * @return an instance of the desired interface
374 */
375#define INTERFACE_GENERATOR(interface_class) \
376 Interface *private_new##interface_class() \
377 { \
378 return new interface_class(); \
379 }
380
381/** Interface delete function for this plugin.
382 * @return an instance of the desired interface
383 */
384#define INTERFACE_DELETER(interface_class) \
385 void private_delete##interface_class(interface_class *interface) \
386 { \
387 delete interface; \
388 }
389
390/** Interface factory function.
391 * @return an instance of the desired interface
392 */
393#define INTERFACE_FACTORY(interface_class) \
394 extern "C" Interface *interface_factory() \
395 { \
396 return private_new##interface_class(); \
397 }
398
399/** Interface destruction function.
400 * @param interface The interface that is to be destroyed.
401 */
402#define INTERFACE_DESTROY(interface_class) \
403 extern "C" void interface_destroy(interface_class *interface) \
404 { \
405 private_delete##interface_class(interface); \
406 }
407
408/** Export interface.
409 * This will create appropriate interface factory and destroy functions.
410 */
411#define EXPORT_INTERFACE(interface_class) \
412 INTERFACE_GENERATOR(interface_class) \
413 INTERFACE_DELETER(interface_class) \
414 INTERFACE_FACTORY(interface_class) \
415 INTERFACE_DESTROY(interface_class)
416
417} // end namespace fawkes
418
419#endif
BlackBoard instance factory.
BlackBoard interface manager.
Interface proxy for remote BlackBoard.
BlackBoard message manager.
This is supposed to be the central clock in Fawkes.
Definition: clock.h:35
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
Interface mediator 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
bool msgq_first_is()
Check if first message has desired type.
Definition: interface.h:351
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
virtual Message * create_message(const char *type) const =0
Create message based on type name.
bool is_writer() const
Check if this is a writing instance.
Definition: interface.cpp:445
void set_field(FieldT &field, DataT &data)
Set a field, set data_changed to true and update data_changed accordingly.
Definition: interface.h:304
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
virtual const char * enum_tostring(const char *enumtype, int val) const =0
Convert arbitrary enum value to string.
Uuid serial() const
Get instance serial of interface.
Definition: interface.cpp:695
bool msgq_empty()
Check if queue is empty.
Definition: interface.cpp:1062
virtual void copy_values(const Interface *interface)=0
Copy values from another interface.
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
MessageType * msgq_first_safe(MessageType *&msg) noexcept
Get first message casted to the desired type without exceptions.
Definition: interface.h:340
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.
Message mediator interface.
Message queue used in interfaces.
Definition: message_queue.h:42
Message * first()
Get first message from queue.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
Mutex mutual exclusion lock.
Definition: mutex.h:33
Read/write lock with reference counting.
Definition: refc_rwlock.h:33
A class for handling time.
Definition: time.h:93
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
void(* InterfaceDestroyFunc)(Interface *interface)
Interface destructor function for the shared library.
Definition: interface.h:360
interface_fieldtype_t
Interface field type.
Definition: types.h:36
bool change_field(FieldT &field, const DataT &value)
Set a field and return whether it changed.
Definition: change_field.h:37
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