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 <interface/message.h>
27 #include <interface/message_queue.h>
28 #include <core/exception.h>
29 
30 #include <cstddef>
31 #include <list>
32 #define __STD_LIMIT_MACROS
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 #if 0 /* just to make Emacs auto-indent happy */
44 }
45 #endif
46 
47 class RefCountRWLock;
48 class InterfaceMediator;
49 class MessageMediator;
50 class Time;
51 class Clock;
52 class Mutex;
53 
55 {
56  public:
57  InterfaceWriteDeniedException(const char *type, const char *id, const char *msg);
58 };
59 
61 {
62  public:
63  InterfaceMessageEnqueueException(const char *type, const char *id);
64 };
65 
67 {
68  public:
69  InterfaceInvalidMessageException(const Interface *interface, const Message *message);
70 };
71 
72 
74 {
75  public:
76  InterfaceInvalidException(const Interface *interface, const char *method);
77 };
78 
79 class Interface
80 {
81  friend class BlackBoardInterfaceManager;
82  friend class BlackBoardInstanceFactory;
83  friend class BlackBoardMessageManager;
84  friend class BlackBoardInterfaceProxy;
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  unsigned short 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  const Time * timestamp() const;
131  void set_auto_timestamping(bool enabled);
132  void set_timestamp(const Time *t = NULL);
133  void set_clock(Clock *clock);
134  void mark_data_changed();
135 
136  std::list<const char *> get_message_types();
137 
138  unsigned int msgq_enqueue(Message *message);
139  unsigned int msgq_enqueue_copy(Message *message);
140  void msgq_remove(Message *message);
141  void msgq_remove(unsigned int message_id);
142  unsigned int msgq_size();
143  void msgq_flush();
144  void msgq_lock();
145  bool msgq_try_lock();
146  void msgq_unlock();
147  void msgq_pop();
148  Message * msgq_first();
149  bool msgq_empty();
150  void msgq_append(Message *message);
151 
152  /** Check if first message has desired type.
153  * @return true, if message has desired type, false otherwise
154  */
155  template <class MessageType>
156  bool msgq_first_is();
157 
158  /** Get first message casted to the desired type.
159  * @return message casted to desired type
160  * @exception TypeMismatchException thrown if message is not of desired type
161  */
162  template <class MessageType>
163  MessageType * msgq_first();
164 
165  /** Get first message casted to the desired type.
166  * @param msg reference to pointer to message of desired type, upon successful
167  * return points to the message.
168  * @return message casted to desired type (same as msg parameter)
169  * @exception TypeMismatchException thrown if message is not of desired type
170  */
171  template <class MessageType>
172  MessageType * msgq_first(MessageType *&msg);
173 
174  /** Get first message casted to the desired type without exceptions.
175  * This method allows to combine a call to msgq_first_is() and msgq_first()
176  * into a single call.
177  * @param msg reference to pointer to message of desired type, upon successful
178  * return points to the message.
179  * @return pointer to message if it is of the desired type, 0 otherwise
180  */
181  template <class MessageType>
182  MessageType * msgq_first_safe(MessageType *&msg) throw();
183 
184  MessageQueue::MessageIterator msgq_begin();
186 
187  /* Introspection */
188 
189  /** Message info list */
191  const char *type; /**< the type of the message */
192  interface_messageinfo_t *next; /**< the next field, NULL if last */
193  };
194 
195  /** Timestamp data, must be present and first entries for each interface
196  * data structs! This leans on timeval struct. */
197  typedef struct {
198  int64_t timestamp_sec; /**< time in seconds since Unix epoch */
199  int64_t timestamp_usec; /**< additional time microseconds */
201 
202  InterfaceFieldIterator fields();
203  InterfaceFieldIterator fields_end();
204 
205  unsigned int num_fields();
206 
207  /* Convenience */
208  static void parse_uid(const char *uid, std::string &type, std::string &id);
209 
210  protected:
211  Interface();
212  virtual bool message_valid(const Message *message) const = 0;
213 
214  void set_hash(unsigned char *ihash);
215  void add_fieldinfo(interface_fieldtype_t type, const char *name,
216  size_t length, void *value,
217  const char *enumtype = 0, const interface_enum_map_t *enum_map = 0);
218  void add_messageinfo(const char *name);
219 
220  void *data_ptr;
221  unsigned int data_size;
223 
225 
226  private:
227  void set_type_id(const char *type, const char *id);
228  void set_instance_serial(unsigned short instance_serial);
229  void set_mediators(InterfaceMediator *iface_mediator,
230  MessageMediator *msg_mediator);
231  void set_memory(unsigned int serial, void *real_ptr, void *data_ptr);
232  void set_readwrite(bool write_access, RefCountRWLock *rwlock);
233  void set_owner(const char *owner);
234 
235  inline unsigned int next_msg_id()
236  {
237  return (__instance_serial << 16) | ++__next_message_id;
238  }
239 
240  char __type[__INTERFACE_TYPE_SIZE + 1];
241  char __id[__INTERFACE_ID_SIZE + 1];
242  char __uid[__INTERFACE_UID_SIZE + 1];
243  unsigned char __hash[__INTERFACE_HASH_SIZE];
244  char __hash_printable[__INTERFACE_HASH_SIZE * 2 + 1];
245  char *__owner;
246 
247  unsigned short __instance_serial;
248  bool __valid;
249 
250  void * __mem_data_ptr;
251  void * __mem_real_ptr;
252  unsigned int __mem_serial;
253  bool __write_access;
254 
255  void * __buffers;
256  unsigned int __num_buffers;
257 
258  Mutex *__data_mutex;
259  RefCountRWLock *__rwlock;
260 
261  InterfaceMediator *__interface_mediator;
262  MessageMediator *__message_mediator;
263  MessageQueue *__message_queue;
264  unsigned short __next_message_id;
265 
266  interface_fieldinfo_t *__fieldinfo_list;
267  interface_messageinfo_t *__messageinfo_list;
268 
269  unsigned int __num_fields;
270 
271  Clock *__clock;
272  Time *__timestamp;
273  Time *__local_read_timestamp;
274  bool __auto_timestamping;
275 };
276 
277 
278 template <class MessageType>
279 MessageType *
281 {
282  MessageType *m = dynamic_cast<MessageType *>(__message_queue->first());
283  if (m) {
284  return m;
285  } else {
286  throw TypeMismatchException("Message is not of desired type");
287  }
288 }
289 
290 
291 template <class MessageType>
292 MessageType *
293 Interface::msgq_first(MessageType *&msg)
294 {
295  msg = this->msgq_first<MessageType>();
296  return msg;
297 }
298 
299 
300 template <class MessageType>
301 MessageType *
302 Interface::msgq_first_safe(MessageType *&msg) throw()
303 {
304  msg = dynamic_cast<MessageType *>(__message_queue->first());
305  return msg;
306 }
307 
308 
309 /** Check if first message has desired type.
310  * @return true, if message has desired type, false otherwise
311  */
312 template <class MessageType>
313 bool
315 {
316  return (dynamic_cast<MessageType *>(__message_queue->first()) != 0);
317 }
318 
319 
320 /** Interface destructor function for the shared library.
321  * Do not use directly. Use EXPORT_INTERFACE macro.
322  * @param interface Interface to destroy
323  */
324 typedef void (* InterfaceDestroyFunc) (Interface *interface);
325 
326 /** Interface generator function for the shared library
327  * Do not use directly. Use EXPORT_INTERFACE macro.
328  */
329 typedef Interface * (* InterfaceFactoryFunc) (void);
330 
331 
332 /** Friend for interface generator function. */
333 #define INTERFACE_MGMT_FRIENDS(interface_class) \
334  friend Interface * private_new##interface_class(); \
335  friend void private_delete##interface_class(interface_class *interface);
336 
337 /** Interface generator function for this plugin.
338  * @return an instance of the desired interface
339  */
340 #define INTERFACE_GENERATOR(interface_class) \
341  Interface * \
342  private_new##interface_class() \
343  { \
344  return new interface_class(); \
345  }
346 
347 
348 /** Interface delete function for this plugin.
349  * @return an instance of the desired interface
350  */
351 #define INTERFACE_DELETER(interface_class) \
352  void \
353  private_delete##interface_class(interface_class *interface) \
354  { \
355  delete interface; \
356  }
357 
358 
359 /** Interface factory function.
360  * @return an instance of the desired interface
361  */
362 #define INTERFACE_FACTORY(interface_class) \
363  extern "C" \
364  Interface * \
365  interface_factory() \
366  { \
367  return private_new##interface_class(); \
368  }
369 
370 
371 /** Interface destruction function.
372  * @param interface The interface that is to be destroyed.
373  */
374 #define INTERFACE_DESTROY(interface_class) \
375  extern "C" \
376  void \
377  interface_destroy(interface_class *interface) \
378  { \
379  private_delete##interface_class(interface); \
380  }
381 
382 /** Export interface.
383  * This will create appropriate interface factory and destroy functions.
384  */
385 #define EXPORT_INTERFACE(interface_class) \
386  INTERFACE_GENERATOR(interface_class) \
387  INTERFACE_DELETER(interface_class) \
388  INTERFACE_FACTORY(interface_class) \
389  INTERFACE_DESTROY(interface_class)
390 
391 } // end namespace fawkes
392 
393 #endif
Interface field iterator.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
Definition: interface.h:73
int64_t timestamp_sec
time in seconds since Unix epoch
Definition: interface.h:198
BlackBoard instance factory.
const char * type
the type of the message
Definition: interface.h:191
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:60
Interface field info list.
Definition: types.h:56
Fawkes library namespace.
interface_messageinfo_t * next
the next field, NULL if last
Definition: interface.h:192
unsigned int data_size
Minimal data size to hold data storage.
Definition: interface.h:221
This is supposed to be the central clock in Fawkes.
Definition: clock.h:34
A class for handling time.
Definition: time.h:91
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
This exception is thrown if a message has been queued in the interface which is not recognized by the...
Definition: interface.h:66
bool data_changed
Indicator if data has changed.
Definition: interface.h:222
void * data_ptr
Pointer to local memory storage.
Definition: interface.h:220
Base class for exceptions in Fawkes.
Definition: exception.h:36
Message * msgq_first()
Get the first message from the message queue.
Definition: interface.cpp:1180
InterfaceWriteDeniedException(const char *type, const char *id, const char *msg)
Constructor.
Definition: interface.cpp:55
Interface proxy for remote BlackBoard.
int64_t timestamp_usec
additional time microseconds
Definition: interface.h:199
Read/write lock with reference counting.
Definition: refc_rwlock.h:33
void(* InterfaceDestroyFunc)(Interface *interface)
Interface destructor function for the shared library.
Definition: interface.h:324
Message queue used in interfaces.
Definition: message_queue.h:42
Timestamp data, must be present and first entries for each interface data structs! This leans on time...
Definition: interface.h:197
Interface mediator interface.
bool msgq_first_is()
Check if first message has desired type.
Definition: interface.h:314
MessageType * msgq_first_safe(MessageType *&msg)
Get first message casted to the desired type without exceptions.
Definition: interface.h:302
BlackBoard message manager.
void set_type_id(const char *id)
Set exception type ID.
Definition: exception.cpp:292
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
Definition: interface.h:224
Mutex mutual exclusion lock.
Definition: mutex.h:32
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:54
interface_fieldtype_t
Interface field type.
Definition: types.h:35
std::map< int, std::string > interface_enum_map_t
Map of enum integer to string values.
Definition: types.h:53
BlackBoard interface manager.
Message mediator interface.