Fawkes API
Fawkes Development Version
|
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