interface.h

00001 
00002 /***************************************************************************
00003  *  interface.h - BlackBoard Interface
00004  *
00005  *  Created: Mon Oct 09 18:34:11 2006
00006  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #ifndef __INTERFACE_H_
00025 #define __INTERFACE_H_
00026 
00027 #include <interface/message.h>
00028 #include <interface/message_queue.h>
00029 #include <core/exception.h>
00030 
00031 #include <cstddef>
00032 #include <list>
00033 #define __STD_LIMIT_MACROS
00034 #include <stdint.h>
00035 
00036 #define __INTERFACE_TYPE_SIZE   32
00037 #define __INTERFACE_ID_SIZE     32
00038 // We use MD5 as interface hash
00039 #define __INTERFACE_HASH_SIZE   16
00040 //  UID is:                                   type  ::   id
00041 #define __INTERFACE_UID_SIZE __INTERFACE_TYPE_SIZE + 2 + __INTERFACE_ID_SIZE
00042 
00043 namespace fawkes {
00044 #if 0 /* just to make Emacs auto-indent happy */
00045 }
00046 #endif
00047 
00048 class RefCountRWLock;
00049 class InterfaceMediator;
00050 class MessageMediator;
00051 class Time;
00052 class Clock;
00053 
00054 class InterfaceWriteDeniedException : public Exception
00055 {
00056  public:
00057   InterfaceWriteDeniedException(const char *type, const char *id, const char *msg);
00058 };
00059 
00060 class InterfaceMessageEnqueueException : public Exception
00061 {
00062  public:
00063   InterfaceMessageEnqueueException(const char *type, const char *id);
00064 };
00065 
00066 class InterfaceInvalidMessageException : public Exception
00067 {
00068  public:
00069   InterfaceInvalidMessageException(const Interface *interface, const Message *message);
00070 };
00071 
00072 
00073 class InterfaceInvalidException : public Exception
00074 {
00075  public:
00076   InterfaceInvalidException(const Interface *interface, const char *method);
00077 };
00078 
00079 class Interface
00080 {
00081  friend class BlackBoardInterfaceManager;
00082  friend class BlackBoardInstanceFactory;
00083  friend class BlackBoardMessageManager;
00084  friend class BlackBoardInterfaceProxy;
00085 
00086  public:
00087   virtual ~Interface();
00088 
00089   bool                    oftype(const char *interface_type) const;
00090   const void *            datachunk() const;
00091   unsigned int            datasize() const;
00092   const char *            type() const;
00093   const char *            id() const;
00094   const char *            uid() const;
00095   unsigned short          serial() const;
00096   unsigned int            mem_serial() const;
00097   bool                    operator== (Interface &comp) const;
00098   const unsigned char *   hash() const;
00099   size_t                  hash_size() const;
00100   const char *            hash_printable() const;
00101   bool                    is_writer() const;
00102   void                    set_validity(bool valid);
00103   bool                    is_valid() const;
00104 
00105   void                    set_from_chunk(void *chunk);
00106 
00107   virtual Message *       create_message(const char *type) const = 0;
00108   virtual void            copy_values(const Interface *interface) = 0;
00109   virtual const char *    enum_tostring(const char *enumtype, int val) const = 0;
00110 
00111   void          read();
00112   void          write();
00113 
00114   bool          has_writer() const;
00115   unsigned int  num_readers() const;
00116 
00117   bool          changed() const;
00118   const Time *  timestamp() const;
00119   void          set_auto_timestamping(bool enabled);
00120   void          set_timestamp(const Time *t = NULL);
00121   void          set_clock(Clock *clock);
00122 
00123   std::list<const char *> get_message_types();
00124 
00125   unsigned int  msgq_enqueue(Message *message);
00126   unsigned int  msgq_enqueue_copy(Message *message);
00127   void          msgq_remove(Message *message);
00128   void          msgq_remove(unsigned int message_id);
00129   unsigned int  msgq_size();
00130   void          msgq_flush();
00131   void          msgq_lock();
00132   bool          msgq_try_lock();
00133   void          msgq_unlock();
00134   void          msgq_pop();
00135   Message *     msgq_first();
00136   bool          msgq_empty();
00137 
00138   /** Check if first message has desired type.
00139    * @return true, if message has desired type, false otherwise
00140    */
00141   template <class MessageType>
00142     bool           msgq_first_is();
00143 
00144   /** Get first message casted to the desired type.
00145    * @return message casted to desired type
00146    * @exception TypeMismatchException thrown if message is not of desired type
00147    */
00148   template <class MessageType>
00149     MessageType *  msgq_first();
00150 
00151   /** Get first message casted to the desired type.
00152    * @param msg reference to pointer to message of desired type, upon successful
00153    * return points to the message. 
00154    * @return message casted to desired type (same as msg parameter)
00155    * @exception TypeMismatchException thrown if message is not of desired type
00156    */
00157   template <class MessageType>
00158     MessageType *  msgq_first(MessageType *&msg);
00159 
00160   MessageQueue::MessageIterator  msgq_begin();
00161   MessageQueue::MessageIterator  msgq_end();
00162 
00163   /* Introspection */
00164 
00165   /** Message info list */
00166   struct interface_messageinfo_t {
00167     const char              *type;   /**< the type of the message */
00168     interface_messageinfo_t *next;   /**< the next field, NULL if last */
00169   };
00170 
00171   InterfaceFieldIterator fields();
00172   InterfaceFieldIterator fields_end();
00173 
00174   unsigned int num_fields();
00175 
00176   /* Convenience */
00177   static void parse_uid(const char *uid, char **type, char **id);
00178 
00179  protected:
00180   Interface();
00181   virtual bool  message_valid(const Message *message) const = 0;
00182 
00183   void set_hash(unsigned char *ihash);
00184   void add_fieldinfo(interface_fieldtype_t type, const char *name,
00185                      size_t length, void *value, const char *enumtype = 0);
00186   void add_messageinfo(const char *name);
00187 
00188   void         *data_ptr;
00189   unsigned int  data_size;
00190   bool          data_changed;
00191 
00192   /** Timestamp data, must be present and first entries for each interface
00193    * data structs! This leans on timeval struct. */
00194   typedef struct {
00195     int64_t timestamp_sec;      /**< time in seconds since Unix epoch */
00196     int64_t timestamp_usec;     /**< additional time microseconds */
00197   } interface_data_ts_t;
00198   interface_data_ts_t  *data_ts;
00199 
00200  private:
00201   void msgq_append(Message *message);
00202   void set_type_id(const char *type, const char *id);
00203   void set_instance_serial(unsigned short instance_serial);
00204   void set_mediators(InterfaceMediator *iface_mediator,
00205                                    MessageMediator *msg_mediator);
00206   void set_memory(unsigned int serial, void *real_ptr, void *data_ptr);
00207   void set_readwrite(bool write_access, RefCountRWLock *rwlock);
00208 
00209   inline unsigned int next_msg_id()
00210   {
00211     return (__instance_serial << 16) | ++__next_message_id;
00212   }
00213 
00214   char               __type[__INTERFACE_TYPE_SIZE + 1];
00215   char               __id[__INTERFACE_ID_SIZE + 1];
00216   char               __uid[__INTERFACE_UID_SIZE + 1];
00217   unsigned char      __hash[__INTERFACE_HASH_SIZE];
00218   char               __hash_printable[__INTERFACE_HASH_SIZE * 2 + 1];
00219 
00220   unsigned short     __instance_serial;
00221   bool               __valid;
00222 
00223   void *             __mem_data_ptr;
00224   void *             __mem_real_ptr;
00225   unsigned int       __mem_serial;
00226   bool               __write_access;
00227 
00228   RefCountRWLock    *__rwlock;
00229 
00230   InterfaceMediator *__interface_mediator;
00231   MessageMediator   *__message_mediator;
00232   MessageQueue      *__message_queue;
00233   unsigned short     __next_message_id;
00234 
00235   interface_fieldinfo_t   *__fieldinfo_list;
00236   interface_messageinfo_t *__messageinfo_list;
00237 
00238   unsigned int       __num_fields;
00239 
00240   Clock             *__clock;
00241   Time              *__timestamp;
00242   Time              *__local_read_timestamp;
00243   bool               __auto_timestamping;
00244 };
00245 
00246 
00247 template <class MessageType>
00248 MessageType *
00249 Interface::msgq_first()
00250 {
00251   MessageType *m = dynamic_cast<MessageType *>(__message_queue->first());
00252   if (m) {
00253     return m;
00254   } else {
00255     throw TypeMismatchException("Message is not of desired type");
00256   }
00257 }
00258 
00259 
00260 template <class MessageType>
00261 MessageType *
00262 Interface::msgq_first(MessageType *&msg)
00263 {
00264   msg = this->msgq_first<MessageType>();
00265   return msg;
00266 }
00267 
00268 
00269 /** Check if first message has desired type.
00270  * @return true, if message has desired type, false otherwise
00271  */
00272 template <class MessageType>
00273 bool
00274 Interface::msgq_first_is()
00275 {
00276   return (dynamic_cast<MessageType *>(__message_queue->first()) != 0);
00277 }
00278 
00279 
00280 /** Interface destructor function for the shared library.
00281  * Do not use directly. Use EXPORT_INTERFACE macro.
00282  * @param interface Interface to destroy
00283  */
00284 typedef void         (* InterfaceDestroyFunc)  (Interface *interface);
00285 
00286 /** Interface generator function for the shared library
00287  * Do not use directly. Use EXPORT_INTERFACE macro.
00288  */
00289 typedef Interface *  (* InterfaceFactoryFunc)  (void);
00290 
00291 
00292 /** Friend for interface generator function. */
00293 #define INTERFACE_MGMT_FRIENDS(interface_class)                         \
00294   friend Interface * private_new##interface_class();                    \
00295   friend void private_delete##interface_class(interface_class *interface);
00296 
00297 /** Interface generator function for this plugin.
00298  * @return an instance of the desired interface
00299  */
00300 #define INTERFACE_GENERATOR(interface_class)                    \
00301   Interface *                                                   \
00302   private_new##interface_class()                                \
00303   {                                                             \
00304     return new interface_class();                               \
00305   }
00306 
00307 
00308 /** Interface delete function for this plugin.
00309  * @return an instance of the desired interface
00310  */
00311 #define INTERFACE_DELETER(interface_class)                      \
00312   void                                                          \
00313   private_delete##interface_class(interface_class *interface)   \
00314   {                                                             \
00315     delete interface;                                           \
00316   }
00317 
00318 
00319 /** Interface factory function.
00320  * @return an instance of the desired interface
00321  */
00322 #define INTERFACE_FACTORY(interface_class)                      \
00323   extern "C"                                                    \
00324   Interface *                                                   \
00325   interface_factory()                                           \
00326   {                                                             \
00327     return private_new##interface_class();                      \
00328   }
00329 
00330 
00331 /** Interface destruction function.
00332  * @param interface The interface that is to be destroyed.
00333  */
00334 #define INTERFACE_DESTROY(interface_class)              \
00335   extern "C"                                            \
00336   void                                                  \
00337   interface_destroy(interface_class *interface)         \
00338   {                                                     \
00339     private_delete##interface_class(interface);         \
00340   }
00341 
00342 /** Export interface.
00343  * This will create appropriate interface factory and destroy functions.
00344  */
00345 #define EXPORT_INTERFACE(interface_class) \
00346   INTERFACE_GENERATOR(interface_class)    \
00347   INTERFACE_DELETER(interface_class)      \
00348   INTERFACE_FACTORY(interface_class)      \
00349   INTERFACE_DESTROY(interface_class)
00350 
00351 } // end namespace fawkes
00352 
00353 #endif

Generated on Tue Feb 22 13:31:26 2011 for Fawkes API by  doxygen 1.4.7