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-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #ifndef __INTERFACE_H_
25 #define __INTERFACE_H_
26 
27 #include <interface/message.h>
28 #include <interface/message_queue.h>
29 #include <core/exception.h>
30 
31 #include <cstddef>
32 #include <list>
33 #define __STD_LIMIT_MACROS
34 #include <stdint.h>
35 
36 #define __INTERFACE_TYPE_SIZE 32
37 #define __INTERFACE_ID_SIZE 32
38 // We use MD5 as interface hash
39 #define __INTERFACE_HASH_SIZE 16
40 // UID is: type :: id
41 #define __INTERFACE_UID_SIZE __INTERFACE_TYPE_SIZE + 2 + __INTERFACE_ID_SIZE
42 
43 namespace fawkes {
44 #if 0 /* just to make Emacs auto-indent happy */
45 }
46 #endif
47 
48 class RefCountRWLock;
49 class InterfaceMediator;
50 class MessageMediator;
51 class Time;
52 class Clock;
53 class Mutex;
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 
73 
75 {
76  public:
77  InterfaceInvalidException(const Interface *interface, const char *method);
78 };
79 
80 class Interface
81 {
82  friend class BlackBoardInterfaceManager;
83  friend class BlackBoardInstanceFactory;
84  friend class BlackBoardMessageManager;
85  friend class BlackBoardInterfaceProxy;
86 
87  public:
88  virtual ~Interface();
89 
90  bool oftype(const char *interface_type) const;
91  const void * datachunk() const;
92  unsigned int datasize() const;
93  const char * type() const;
94  const char * id() const;
95  const char * uid() const;
96  unsigned short serial() const;
97  unsigned int mem_serial() const;
98  bool operator== (Interface &comp) const;
99  const unsigned char * hash() const;
100  size_t hash_size() const;
101  const char * hash_printable() const;
102  bool is_writer() const;
103  void set_validity(bool valid);
104  bool is_valid() 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 
119  void read();
120  void write();
121 
122  bool has_writer() const;
123  unsigned int num_readers() const;
124 
125  bool changed() const;
126  const Time * timestamp() const;
127  void set_auto_timestamping(bool enabled);
128  void set_timestamp(const Time *t = NULL);
129  void set_clock(Clock *clock);
130 
131  std::list<const char *> get_message_types();
132 
133  unsigned int msgq_enqueue(Message *message);
134  unsigned int msgq_enqueue_copy(Message *message);
135  void msgq_remove(Message *message);
136  void msgq_remove(unsigned int message_id);
137  unsigned int msgq_size();
138  void msgq_flush();
139  void msgq_lock();
140  bool msgq_try_lock();
141  void msgq_unlock();
142  void msgq_pop();
143  Message * msgq_first();
144  bool msgq_empty();
145 
146  /** Check if first message has desired type.
147  * @return true, if message has desired type, false otherwise
148  */
149  template <class MessageType>
150  bool msgq_first_is();
151 
152  /** Get first message casted to the desired type.
153  * @return message casted to desired type
154  * @exception TypeMismatchException thrown if message is not of desired type
155  */
156  template <class MessageType>
157  MessageType * msgq_first();
158 
159  /** Get first message casted to the desired type.
160  * @param msg reference to pointer to message of desired type, upon successful
161  * return points to the message.
162  * @return message casted to desired type (same as msg parameter)
163  * @exception TypeMismatchException thrown if message is not of desired type
164  */
165  template <class MessageType>
166  MessageType * msgq_first(MessageType *&msg);
167 
168  /** Get first message casted to the desired type without exceptions.
169  * This method allows to combine a call to msgq_first_is() and msgq_first()
170  * into a single call.
171  * @param msg reference to pointer to message of desired type, upon successful
172  * return points to the message.
173  * @return pointer to message if it is of the desired type, 0 otherwise
174  */
175  template <class MessageType>
176  MessageType * msgq_first_safe(MessageType *&msg) throw();
177 
178  MessageQueue::MessageIterator msgq_begin();
180 
181  /* Introspection */
182 
183  /** Message info list */
185  const char *type; /**< the type of the message */
186  interface_messageinfo_t *next; /**< the next field, NULL if last */
187  };
188 
189  InterfaceFieldIterator fields();
190  InterfaceFieldIterator fields_end();
191 
192  unsigned int num_fields();
193 
194  /* Convenience */
195  static void parse_uid(const char *uid, char **type, char **id);
196 
197  protected:
198  Interface();
199  virtual bool message_valid(const Message *message) const = 0;
200 
201  void set_hash(unsigned char *ihash);
202  void add_fieldinfo(interface_fieldtype_t type, const char *name,
203  size_t length, void *value, const char *enumtype = 0);
204  void add_messageinfo(const char *name);
205 
206  void *data_ptr;
207  unsigned int data_size;
209 
210  /** Timestamp data, must be present and first entries for each interface
211  * data structs! This leans on timeval struct. */
212  typedef struct {
213  int64_t timestamp_sec; /**< time in seconds since Unix epoch */
214  int64_t timestamp_usec; /**< additional time microseconds */
217 
218  private:
219  void msgq_append(Message *message);
220  void set_type_id(const char *type, const char *id);
221  void set_instance_serial(unsigned short instance_serial);
222  void set_mediators(InterfaceMediator *iface_mediator,
223  MessageMediator *msg_mediator);
224  void set_memory(unsigned int serial, void *real_ptr, void *data_ptr);
225  void set_readwrite(bool write_access, RefCountRWLock *rwlock);
226 
227  inline unsigned int next_msg_id()
228  {
229  return (__instance_serial << 16) | ++__next_message_id;
230  }
231 
232  char __type[__INTERFACE_TYPE_SIZE + 1];
233  char __id[__INTERFACE_ID_SIZE + 1];
234  char __uid[__INTERFACE_UID_SIZE + 1];
235  unsigned char __hash[__INTERFACE_HASH_SIZE];
236  char __hash_printable[__INTERFACE_HASH_SIZE * 2 + 1];
237 
238  unsigned short __instance_serial;
239  bool __valid;
240 
241  void * __mem_data_ptr;
242  void * __mem_real_ptr;
243  unsigned int __mem_serial;
244  bool __write_access;
245 
246  void * __buffers;
247  unsigned int __num_buffers;
248 
249  Mutex *__data_mutex;
250  RefCountRWLock *__rwlock;
251 
252  InterfaceMediator *__interface_mediator;
253  MessageMediator *__message_mediator;
254  MessageQueue *__message_queue;
255  unsigned short __next_message_id;
256 
257  interface_fieldinfo_t *__fieldinfo_list;
258  interface_messageinfo_t *__messageinfo_list;
259 
260  unsigned int __num_fields;
261 
262  Clock *__clock;
263  Time *__timestamp;
264  Time *__local_read_timestamp;
265  bool __auto_timestamping;
266 };
267 
268 
269 template <class MessageType>
270 MessageType *
271 Interface::msgq_first()
272 {
273  MessageType *m = dynamic_cast<MessageType *>(__message_queue->first());
274  if (m) {
275  return m;
276  } else {
277  throw TypeMismatchException("Message is not of desired type");
278  }
279 }
280 
281 
282 template <class MessageType>
283 MessageType *
284 Interface::msgq_first(MessageType *&msg)
285 {
286  msg = this->msgq_first<MessageType>();
287  return msg;
288 }
289 
290 
291 template <class MessageType>
292 MessageType *
293 Interface::msgq_first_safe(MessageType *&msg) throw()
294 {
295  msg = dynamic_cast<MessageType *>(__message_queue->first());
296  return msg;
297 }
298 
299 
300 /** Check if first message has desired type.
301  * @return true, if message has desired type, false otherwise
302  */
303 template <class MessageType>
304 bool
305 Interface::msgq_first_is()
306 {
307  return (dynamic_cast<MessageType *>(__message_queue->first()) != 0);
308 }
309 
310 
311 /** Interface destructor function for the shared library.
312  * Do not use directly. Use EXPORT_INTERFACE macro.
313  * @param interface Interface to destroy
314  */
315 typedef void (* InterfaceDestroyFunc) (Interface *interface);
316 
317 /** Interface generator function for the shared library
318  * Do not use directly. Use EXPORT_INTERFACE macro.
319  */
320 typedef Interface * (* InterfaceFactoryFunc) (void);
321 
322 
323 /** Friend for interface generator function. */
324 #define INTERFACE_MGMT_FRIENDS(interface_class) \
325  friend Interface * private_new##interface_class(); \
326  friend void private_delete##interface_class(interface_class *interface);
327 
328 /** Interface generator function for this plugin.
329  * @return an instance of the desired interface
330  */
331 #define INTERFACE_GENERATOR(interface_class) \
332  Interface * \
333  private_new##interface_class() \
334  { \
335  return new interface_class(); \
336  }
337 
338 
339 /** Interface delete function for this plugin.
340  * @return an instance of the desired interface
341  */
342 #define INTERFACE_DELETER(interface_class) \
343  void \
344  private_delete##interface_class(interface_class *interface) \
345  { \
346  delete interface; \
347  }
348 
349 
350 /** Interface factory function.
351  * @return an instance of the desired interface
352  */
353 #define INTERFACE_FACTORY(interface_class) \
354  extern "C" \
355  Interface * \
356  interface_factory() \
357  { \
358  return private_new##interface_class(); \
359  }
360 
361 
362 /** Interface destruction function.
363  * @param interface The interface that is to be destroyed.
364  */
365 #define INTERFACE_DESTROY(interface_class) \
366  extern "C" \
367  void \
368  interface_destroy(interface_class *interface) \
369  { \
370  private_delete##interface_class(interface); \
371  }
372 
373 /** Export interface.
374  * This will create appropriate interface factory and destroy functions.
375  */
376 #define EXPORT_INTERFACE(interface_class) \
377  INTERFACE_GENERATOR(interface_class) \
378  INTERFACE_DELETER(interface_class) \
379  INTERFACE_FACTORY(interface_class) \
380  INTERFACE_DESTROY(interface_class)
381 
382 } // end namespace fawkes
383 
384 #endif
Interface field iterator.
This exception is thrown if an interface is invalid and it is attempted to call read()/write().
Definition: interface.h:74
int64_t timestamp_sec
time in seconds since Unix epoch
Definition: interface.h:213
BlackBoard instance factory.
const char * type
the type of the message
Definition: interface.h:185
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:43
This exception is thrown if a write has been attempted on a read-only interface.
Definition: interface.h:61
Interface field info list.
Definition: types.h:51
Fawkes library namespace.
interface_messageinfo_t * next
the next field, NULL if last
Definition: interface.h:186
unsigned int data_size
Minimal data size to hold data storage.
Definition: interface.h:207
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:80
This exception is thrown if a message has been queued in the interface which is not recognized by the...
Definition: interface.h:67
bool data_changed
Indicator if data has changed.
Definition: interface.h:208
void * data_ptr
Pointer to local memory storage.
Definition: interface.h:206
Base class for exceptions in Fawkes.
Definition: exception.h:36
Interface proxy for remote BlackBoard.
int64_t timestamp_usec
additional time microseconds
Definition: interface.h:214
Read/write lock with reference counting.
Definition: refc_rwlock.h:33
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:212
Interface mediator interface.
BlackBoard message manager.
interface_data_ts_t * data_ts
Pointer to data casted to timestamp struct.
Definition: interface.h:216
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:55
interface_fieldtype_t
Interface field type.
Definition: types.h:33
BlackBoard interface manager.
Message mediator interface.