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 
42 namespace fawkes {
43 
44 class RefCountRWLock;
45 class InterfaceMediator;
46 class MessageMediator;
47 class Time;
48 class Clock;
49 class Mutex;
50 class BlackBoardInterfaceManager;
51 class BlackBoardInstanceFactory;
52 class BlackBoardMessageManager;
53 class BlackBoardInterfaceProxy;
54 
56 {
57 public:
58  InterfaceWriteDeniedException(const char *type, const char *id, const char *msg);
59 };
60 
62 {
63 public:
64  InterfaceMessageEnqueueException(const char *type, const char *id);
65 };
66 
68 {
69 public:
70  InterfaceInvalidMessageException(const Interface *interface, const Message *message);
71 };
72 
74 {
75 public:
76  InterfaceInvalidException(const Interface *interface, const char *method);
77 };
78 
79 class Interface
80 {
85 
86 public:
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();
150  Message * msgq_first();
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 
214 protected:
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 
251 private:
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 
302 template <class FieldT, class DataT>
303 void
304 Interface::set_field(FieldT &field, DataT &data)
305 {
306  data_changed |= change_field(field, data);
307  data_refreshed = true;
308 }
309 
310 template <class FieldT, class DataT>
311 void
312 Interface::set_field(FieldT &field, unsigned int index, DataT &data)
313 {
314  data_changed |= change_field(field, index, data);
315  data_refreshed = true;
316 }
317 
318 template <class MessageType>
319 MessageType *
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 
330 template <class MessageType>
331 MessageType *
332 Interface::msgq_first(MessageType *&msg)
333 {
334  msg = this->msgq_first<MessageType>();
335  return msg;
336 }
337 
338 template <class MessageType>
339 MessageType *
340 Interface::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  */
349 template <class MessageType>
350 bool
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  */
360 typedef void (*InterfaceDestroyFunc)(Interface *interface);
361 
362 /** Interface generator function for the shared library
363  * Do not use directly. Use EXPORT_INTERFACE macro.
364  */
365 typedef 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