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 class Mutex; 00054 00055 class InterfaceWriteDeniedException : public Exception 00056 { 00057 public: 00058 InterfaceWriteDeniedException(const char *type, const char *id, const char *msg); 00059 }; 00060 00061 class InterfaceMessageEnqueueException : public Exception 00062 { 00063 public: 00064 InterfaceMessageEnqueueException(const char *type, const char *id); 00065 }; 00066 00067 class InterfaceInvalidMessageException : public Exception 00068 { 00069 public: 00070 InterfaceInvalidMessageException(const Interface *interface, const Message *message); 00071 }; 00072 00073 00074 class InterfaceInvalidException : public Exception 00075 { 00076 public: 00077 InterfaceInvalidException(const Interface *interface, const char *method); 00078 }; 00079 00080 class Interface 00081 { 00082 friend class BlackBoardInterfaceManager; 00083 friend class BlackBoardInstanceFactory; 00084 friend class BlackBoardMessageManager; 00085 friend class BlackBoardInterfaceProxy; 00086 00087 public: 00088 virtual ~Interface(); 00089 00090 bool oftype(const char *interface_type) const; 00091 const void * datachunk() const; 00092 unsigned int datasize() const; 00093 const char * type() const; 00094 const char * id() const; 00095 const char * uid() const; 00096 unsigned short serial() const; 00097 unsigned int mem_serial() const; 00098 bool operator== (Interface &comp) const; 00099 const unsigned char * hash() const; 00100 size_t hash_size() const; 00101 const char * hash_printable() const; 00102 bool is_writer() const; 00103 void set_validity(bool valid); 00104 bool is_valid() const; 00105 00106 void set_from_chunk(void *chunk); 00107 00108 virtual Message * create_message(const char *type) const = 0; 00109 virtual void copy_values(const Interface *interface) = 0; 00110 virtual const char * enum_tostring(const char *enumtype, int val) const = 0; 00111 00112 void resize_buffers(unsigned int num_buffers); 00113 unsigned int num_buffers() const; 00114 void copy_shared_to_buffer(unsigned int buffer); 00115 void copy_private_to_buffer(unsigned int buffer); 00116 void read_from_buffer(unsigned int buffer); 00117 int compare_buffers(unsigned int buffer); 00118 00119 void read(); 00120 void write(); 00121 00122 bool has_writer() const; 00123 unsigned int num_readers() const; 00124 00125 bool changed() const; 00126 const Time * timestamp() const; 00127 void set_auto_timestamping(bool enabled); 00128 void set_timestamp(const Time *t = NULL); 00129 void set_clock(Clock *clock); 00130 00131 std::list<const char *> get_message_types(); 00132 00133 unsigned int msgq_enqueue(Message *message); 00134 unsigned int msgq_enqueue_copy(Message *message); 00135 void msgq_remove(Message *message); 00136 void msgq_remove(unsigned int message_id); 00137 unsigned int msgq_size(); 00138 void msgq_flush(); 00139 void msgq_lock(); 00140 bool msgq_try_lock(); 00141 void msgq_unlock(); 00142 void msgq_pop(); 00143 Message * msgq_first(); 00144 bool msgq_empty(); 00145 00146 /** Check if first message has desired type. 00147 * @return true, if message has desired type, false otherwise 00148 */ 00149 template <class MessageType> 00150 bool msgq_first_is(); 00151 00152 /** Get first message casted to the desired type. 00153 * @return message casted to desired type 00154 * @exception TypeMismatchException thrown if message is not of desired type 00155 */ 00156 template <class MessageType> 00157 MessageType * msgq_first(); 00158 00159 /** Get first message casted to the desired type. 00160 * @param msg reference to pointer to message of desired type, upon successful 00161 * return points to the message. 00162 * @return message casted to desired type (same as msg parameter) 00163 * @exception TypeMismatchException thrown if message is not of desired type 00164 */ 00165 template <class MessageType> 00166 MessageType * msgq_first(MessageType *&msg); 00167 00168 /** Get first message casted to the desired type without exceptions. 00169 * This method allows to combine a call to msgq_first_is() and msgq_first() 00170 * into a single call. 00171 * @param msg reference to pointer to message of desired type, upon successful 00172 * return points to the message. 00173 * @return pointer to message if it is of the desired type, 0 otherwise 00174 */ 00175 template <class MessageType> 00176 MessageType * msgq_first_safe(MessageType *&msg) throw(); 00177 00178 MessageQueue::MessageIterator msgq_begin(); 00179 MessageQueue::MessageIterator msgq_end(); 00180 00181 /* Introspection */ 00182 00183 /** Message info list */ 00184 struct interface_messageinfo_t { 00185 const char *type; /**< the type of the message */ 00186 interface_messageinfo_t *next; /**< the next field, NULL if last */ 00187 }; 00188 00189 InterfaceFieldIterator fields(); 00190 InterfaceFieldIterator fields_end(); 00191 00192 unsigned int num_fields(); 00193 00194 /* Convenience */ 00195 static void parse_uid(const char *uid, char **type, char **id); 00196 00197 protected: 00198 Interface(); 00199 virtual bool message_valid(const Message *message) const = 0; 00200 00201 void set_hash(unsigned char *ihash); 00202 void add_fieldinfo(interface_fieldtype_t type, const char *name, 00203 size_t length, void *value, const char *enumtype = 0); 00204 void add_messageinfo(const char *name); 00205 00206 void *data_ptr; 00207 unsigned int data_size; 00208 bool data_changed; 00209 00210 /** Timestamp data, must be present and first entries for each interface 00211 * data structs! This leans on timeval struct. */ 00212 typedef struct { 00213 int64_t timestamp_sec; /**< time in seconds since Unix epoch */ 00214 int64_t timestamp_usec; /**< additional time microseconds */ 00215 } interface_data_ts_t; 00216 interface_data_ts_t *data_ts; 00217 00218 private: 00219 void msgq_append(Message *message); 00220 void set_type_id(const char *type, const char *id); 00221 void set_instance_serial(unsigned short instance_serial); 00222 void set_mediators(InterfaceMediator *iface_mediator, 00223 MessageMediator *msg_mediator); 00224 void set_memory(unsigned int serial, void *real_ptr, void *data_ptr); 00225 void set_readwrite(bool write_access, RefCountRWLock *rwlock); 00226 00227 inline unsigned int next_msg_id() 00228 { 00229 return (__instance_serial << 16) | ++__next_message_id; 00230 } 00231 00232 char __type[__INTERFACE_TYPE_SIZE + 1]; 00233 char __id[__INTERFACE_ID_SIZE + 1]; 00234 char __uid[__INTERFACE_UID_SIZE + 1]; 00235 unsigned char __hash[__INTERFACE_HASH_SIZE]; 00236 char __hash_printable[__INTERFACE_HASH_SIZE * 2 + 1]; 00237 00238 unsigned short __instance_serial; 00239 bool __valid; 00240 00241 void * __mem_data_ptr; 00242 void * __mem_real_ptr; 00243 unsigned int __mem_serial; 00244 bool __write_access; 00245 00246 void * __buffers; 00247 unsigned int __num_buffers; 00248 00249 Mutex *__data_mutex; 00250 RefCountRWLock *__rwlock; 00251 00252 InterfaceMediator *__interface_mediator; 00253 MessageMediator *__message_mediator; 00254 MessageQueue *__message_queue; 00255 unsigned short __next_message_id; 00256 00257 interface_fieldinfo_t *__fieldinfo_list; 00258 interface_messageinfo_t *__messageinfo_list; 00259 00260 unsigned int __num_fields; 00261 00262 Clock *__clock; 00263 Time *__timestamp; 00264 Time *__local_read_timestamp; 00265 bool __auto_timestamping; 00266 }; 00267 00268 00269 template <class MessageType> 00270 MessageType * 00271 Interface::msgq_first() 00272 { 00273 MessageType *m = dynamic_cast<MessageType *>(__message_queue->first()); 00274 if (m) { 00275 return m; 00276 } else { 00277 throw TypeMismatchException("Message is not of desired type"); 00278 } 00279 } 00280 00281 00282 template <class MessageType> 00283 MessageType * 00284 Interface::msgq_first(MessageType *&msg) 00285 { 00286 msg = this->msgq_first<MessageType>(); 00287 return msg; 00288 } 00289 00290 00291 template <class MessageType> 00292 MessageType * 00293 Interface::msgq_first_safe(MessageType *&msg) throw() 00294 { 00295 msg = dynamic_cast<MessageType *>(__message_queue->first()); 00296 return msg; 00297 } 00298 00299 00300 /** Check if first message has desired type. 00301 * @return true, if message has desired type, false otherwise 00302 */ 00303 template <class MessageType> 00304 bool 00305 Interface::msgq_first_is() 00306 { 00307 return (dynamic_cast<MessageType *>(__message_queue->first()) != 0); 00308 } 00309 00310 00311 /** Interface destructor function for the shared library. 00312 * Do not use directly. Use EXPORT_INTERFACE macro. 00313 * @param interface Interface to destroy 00314 */ 00315 typedef void (* InterfaceDestroyFunc) (Interface *interface); 00316 00317 /** Interface generator function for the shared library 00318 * Do not use directly. Use EXPORT_INTERFACE macro. 00319 */ 00320 typedef Interface * (* InterfaceFactoryFunc) (void); 00321 00322 00323 /** Friend for interface generator function. */ 00324 #define INTERFACE_MGMT_FRIENDS(interface_class) \ 00325 friend Interface * private_new##interface_class(); \ 00326 friend void private_delete##interface_class(interface_class *interface); 00327 00328 /** Interface generator function for this plugin. 00329 * @return an instance of the desired interface 00330 */ 00331 #define INTERFACE_GENERATOR(interface_class) \ 00332 Interface * \ 00333 private_new##interface_class() \ 00334 { \ 00335 return new interface_class(); \ 00336 } 00337 00338 00339 /** Interface delete function for this plugin. 00340 * @return an instance of the desired interface 00341 */ 00342 #define INTERFACE_DELETER(interface_class) \ 00343 void \ 00344 private_delete##interface_class(interface_class *interface) \ 00345 { \ 00346 delete interface; \ 00347 } 00348 00349 00350 /** Interface factory function. 00351 * @return an instance of the desired interface 00352 */ 00353 #define INTERFACE_FACTORY(interface_class) \ 00354 extern "C" \ 00355 Interface * \ 00356 interface_factory() \ 00357 { \ 00358 return private_new##interface_class(); \ 00359 } 00360 00361 00362 /** Interface destruction function. 00363 * @param interface The interface that is to be destroyed. 00364 */ 00365 #define INTERFACE_DESTROY(interface_class) \ 00366 extern "C" \ 00367 void \ 00368 interface_destroy(interface_class *interface) \ 00369 { \ 00370 private_delete##interface_class(interface); \ 00371 } 00372 00373 /** Export interface. 00374 * This will create appropriate interface factory and destroy functions. 00375 */ 00376 #define EXPORT_INTERFACE(interface_class) \ 00377 INTERFACE_GENERATOR(interface_class) \ 00378 INTERFACE_DELETER(interface_class) \ 00379 INTERFACE_FACTORY(interface_class) \ 00380 INTERFACE_DESTROY(interface_class) 00381 00382 } // end namespace fawkes 00383 00384 #endif