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
00034 #define __INTERFACE_TYPE_SIZE   32
00035 #define __INTERFACE_ID_SIZE     32
00036 // We use MD5 as interface hash
00037 #define __INTERFACE_HASH_SIZE   16
00038 //  UID is:                                   type  ::   id
00039 #define __INTERFACE_UID_SIZE __INTERFACE_TYPE_SIZE + 2 + __INTERFACE_ID_SIZE
00040 
00041 namespace fawkes {
00042 #if 0 /* just to make Emacs auto-indent happy */
00043 }
00044 #endif
00045 
00046 class RefCountRWLock;
00047 class InterfaceMediator;
00048 class MessageMediator;
00049
00050 class InterfaceWriteDeniedException : public Exception
00051 {
00052  public:
00053   InterfaceWriteDeniedException(const char *type, const char *id, const char *msg);
00054 };
00055
00056 class InterfaceMessageEnqueueException : public Exception
00057 {
00058  public:
00059   InterfaceMessageEnqueueException(const char *type, const char *id);
00060 };
00061
00062 class InterfaceInvalidMessageException : public Exception
00063 {
00064  public:
00065   InterfaceInvalidMessageException(const Interface *interface, const Message *message);
00066 };
00067
00068
00069 class InterfaceInvalidException : public Exception
00070 {
00071  public:
00072   InterfaceInvalidException(const Interface *interface, const char *method);
00073 };
00074
00075 class Interface
00076 {
00077  friend class BlackBoardInterfaceManager;
00078  friend class BlackBoardInstanceFactory;
00079  friend class BlackBoardMessageManager;
00080  friend class BlackBoardInterfaceProxy;
00081
00082  public:
00083   virtual ~Interface();
00084
00085   bool                    oftype(const char *interface_type) const;
00086   const void *            datachunk() const;
00087   unsigned int            datasize() const;
00088   const char *            type() const;
00089   const char *            id() const;
00090   const char *            uid() const;
00091   unsigned short          serial() const;
00092   unsigned int            mem_serial() const;
00093   bool                    operator== (Interface &comp) const;
00094   const unsigned char *   hash() const;
00095   size_t                  hash_size() const;
00096   const char *            hash_printable() const;
00097   bool                    is_writer() const;
00098   void                    set_validity(bool valid);
00099   bool                    is_valid() const;
00100
00101   void                    set_from_chunk(void *chunk);
00102
00103   virtual Message *       create_message(const char *type) const = 0;
00104   virtual void            copy_values(const Interface *interface) = 0;
00105
00106   void          read();
00107   void          write();
00108
00109   bool          has_writer() const;
00110   unsigned int  num_readers() const;
00111
00112
00113   std::list<const char *> get_message_types();
00114
00115   unsigned int  msgq_enqueue(Message *message);
00116   unsigned int  msgq_enqueue_copy(Message *message);
00117   void          msgq_remove(Message *message);
00118   void          msgq_remove(unsigned int message_id);
00119   unsigned int  msgq_size();
00120   void          msgq_flush();
00121   void          msgq_lock();
00122   bool          msgq_try_lock();
00123   void          msgq_unlock();
00124   void          msgq_pop();
00125   Message *     msgq_first();
00126   bool          msgq_empty();
00127 
00128   /** Check if first message has desired type.
00129    * @return true, if message has desired type, false otherwise
00130    */
00131   template <class MessageType>
00132     bool           msgq_first_is();
00133 
00134   /** Get first message casted to the desired type.
00135    * @return message casted to desired type
00136    * @exception TypeMismatchException thrown if message is not of desired type
00137    */
00138   template <class MessageType>
00139     MessageType *  msgq_first();
00140 
00141   /** Get first message casted to the desired type.
00142    * @param msg reference to pointer to message of desired type, upon successful
00143    * return points to the message. 
00144    * @return message casted to desired type (same as msg parameter)
00145    * @exception TypeMismatchException thrown if message is not of desired type
00146    */
00147   template <class MessageType>
00148     MessageType *  msgq_first(MessageType *&msg);
00149
00150   MessageQueue::MessageIterator  msgq_begin();
00151   MessageQueue::MessageIterator  msgq_end();
00152
00153   /* Introspection */
00154 
00155   /** Message info list */
00156   struct interface_messageinfo_t {
00157     const char              *type;   /**< the type of the message */
00158     interface_messageinfo_t *next;   /**< the next field, NULL if last */
00159   };
00160
00161   InterfaceFieldIterator fields();
00162   InterfaceFieldIterator fields_end();
00163
00164   unsigned int num_fields();
00165
00166  protected:
00167   Interface();
00168   virtual bool  message_valid(const Message *message) const = 0;
00169
00170   void set_hash(unsigned char *ihash);
00171   void add_fieldinfo(interface_fieldtype_t type, const char *name,
00172                      size_t length, void *value);
00173   void add_messageinfo(const char *name);
00174
00175   void         *data_ptr;
00176   unsigned int  data_size;
00177
00178  private:
00179   void msgq_append(Message *message);
00180   void set_type_id(const char *type, const char *id);
00181   void set_instance_serial(unsigned short instance_serial);
00182   void set_mediators(InterfaceMediator *iface_mediator,
00183                                    MessageMediator *msg_mediator);
00184   void set_memory(unsigned int serial, void *real_ptr, void *data_ptr);
00185   void set_readwrite(bool write_access, RefCountRWLock *rwlock);
00186
00187   inline unsigned int next_msg_id()
00188   {
00189     return (__instance_serial << 16) | ++__next_message_id;
00190   }
00191
00192   char               __type[__INTERFACE_TYPE_SIZE + 1];
00193   char               __id[__INTERFACE_ID_SIZE + 1];
00194   char               __uid[__INTERFACE_UID_SIZE + 1];
00195   unsigned char      __hash[__INTERFACE_HASH_SIZE];
00196   char               __hash_printable[__INTERFACE_HASH_SIZE * 2 + 1];
00197
00198   unsigned short     __instance_serial;
00199   bool               __valid;
00200
00201   void *             __mem_data_ptr;
00202   void *             __mem_real_ptr;
00203   unsigned int       __mem_serial;
00204   bool               __write_access;
00205
00206   RefCountRWLock    *__rwlock;
00207
00208   InterfaceMediator *__interface_mediator;
00209   MessageMediator   *__message_mediator;
00210   MessageQueue      *__message_queue;
00211   unsigned short     __next_message_id;
00212
00213   interface_fieldinfo_t   *__fieldinfo_list;
00214   interface_messageinfo_t *__messageinfo_list;
00215
00216   unsigned int       __num_fields;
00217 };
00218
00219
00220 template <class MessageType>
00221 MessageType *
00222 Interface::msgq_first()
00223 {
00224   MessageType *m = dynamic_cast<MessageType *>(__message_queue->first());
00225   if (m) {
00226     return m;
00227   } else {
00228     throw TypeMismatchException("Message is not of desired type");
00229   }
00230 }
00231
00232
00233 template <class MessageType>
00234 MessageType *
00235 Interface::msgq_first(MessageType *&msg)
00236 {
00237   msg = this->msgq_first<MessageType>();
00238   return msg;
00239 }
00240
00241 
00242 /** Check if first message has desired type.
00243  * @return true, if message has desired type, false otherwise
00244  */
00245 template <class MessageType>
00246 bool
00247 Interface::msgq_first_is()
00248 {
00249   return (dynamic_cast<MessageType *>(__message_queue->first()) != 0);
00250 }
00251
00252 
00253 /** Interface destructor function for the shared library.
00254  * Do not use directly. Use EXPORT_INTERFACE macro.
00255  * @param interface Interface to destroy
00256  */
00257 typedef void         (* InterfaceDestroyFunc)  (Interface *interface);
00258 
00259 /** Interface generator function for the shared library
00260  * Do not use directly. Use EXPORT_INTERFACE macro.
00261  */
00262 typedef Interface *  (* InterfaceFactoryFunc)  (void);
00263
00264 
00265 /** Friend for interface generator function. */
00266 #define INTERFACE_MGMT_FRIENDS(interface_class)                         \
00267   friend Interface * private_new##interface_class();                    \
00268   friend void private_delete##interface_class(interface_class *interface);
00269 
00270 /** Interface generator function for this plugin.
00271  * @return an instance of the desired interface
00272  */
00273 #define INTERFACE_GENERATOR(interface_class)                    \
00274   Interface *                                                   \
00275   private_new##interface_class()                                \
00276   {                                                             \
00277     return new interface_class();                               \
00278   }
00279 
00280 
00281 /** Interface delete function for this plugin.
00282  * @return an instance of the desired interface
00283  */
00284 #define INTERFACE_DELETER(interface_class)                      \
00285   void                                                          \
00286   private_delete##interface_class(interface_class *interface)   \
00287   {                                                             \
00288     delete interface;                                           \
00289   }
00290 
00291 
00292 /** Interface factory function.
00293  * @return an instance of the desired interface
00294  */
00295 #define INTERFACE_FACTORY(interface_class)                      \
00296   extern "C"                                                    \
00297   Interface *                                                   \
00298   interface_factory()                                           \
00299   {                                                             \
00300     return private_new##interface_class();                      \
00301   }
00302 
00303 
00304 /** Interface destruction function.
00305  * @param interface The interface that is to be destroyed.
00306  */
00307 #define INTERFACE_DESTROY(interface_class)              \
00308   extern "C"                                            \
00309   void                                                  \
00310   interface_destroy(interface_class *interface)         \
00311   {                                                     \
00312     private_delete##interface_class(interface);         \
00313   }
00314 
00315 /** Export interface.
00316  * This will create appropriate interface factory and destroy functions.
00317  */
00318 #define EXPORT_INTERFACE(interface_class) \
00319   INTERFACE_GENERATOR(interface_class)    \
00320   INTERFACE_DELETER(interface_class)      \
00321   INTERFACE_FACTORY(interface_class)      \
00322   INTERFACE_DESTROY(interface_class)
00323 
00324 } // end namespace fawkes
00325
00326 #endif