00001 00002 /*************************************************************************** 00003 * message_queue.h - BlackBoard Interface message queue 00004 * 00005 * Created: Tue Oct 17 19:05:33 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_MESSAGE_QUEUE_H_ 00025 #define __INTERFACE_MESSAGE_QUEUE_H_ 00026 00027 #include <core/exception.h> 00028 #include <core/exceptions/software.h> 00029 00030 namespace fawkes { 00031 00032 class Message; 00033 class Mutex; 00034 00035 00036 class MessageAlreadyQueuedException : public Exception { 00037 public: 00038 MessageAlreadyQueuedException(); 00039 }; 00040 00041 00042 class MessageQueue 00043 { 00044 private: 00045 // define our own list type since std::list is way too fat 00046 /** Message list, internal only 00047 */ 00048 struct msg_list_t { 00049 msg_list_t *next; /**< pointer to next element in list */ 00050 unsigned int msg_id; /**< message id */ 00051 Message *msg; /**< pointer to message */ 00052 }; 00053 00054 public: 00055 MessageQueue(); 00056 virtual ~MessageQueue(); 00057 00058 class MessageIterator 00059 { 00060 friend class MessageQueue; 00061 private: 00062 MessageIterator(msg_list_t *cur); 00063 public: 00064 MessageIterator(); 00065 MessageIterator(const MessageIterator &it); 00066 MessageIterator & operator++ (); // prefix 00067 MessageIterator operator++ (int inc); // postfix 00068 MessageIterator & operator+ (unsigned int i); 00069 MessageIterator & operator+= (unsigned int i); 00070 bool operator== (const MessageIterator & c) const; 00071 bool operator!= (const MessageIterator & c) const; 00072 Message * operator* () const; 00073 Message * operator-> () const; 00074 MessageIterator & operator= (const MessageIterator & c); 00075 00076 unsigned int id() const; 00077 00078 template <class MessageType> 00079 bool is() const; 00080 00081 template <class MessageType> 00082 MessageType * get() const; 00083 00084 private: 00085 msg_list_t *cur; 00086 }; 00087 00088 00089 void append(Message *msg); 00090 void remove(const Message *msg); 00091 void remove(const unsigned int msg_id); 00092 void insert_after(const MessageIterator &it, Message *msg); 00093 00094 unsigned int size() const; 00095 00096 void flush(); 00097 bool empty() const; 00098 00099 void lock(); 00100 bool try_lock(); 00101 void unlock(); 00102 00103 Message * first(); 00104 void pop(); 00105 00106 MessageIterator begin(); 00107 MessageIterator end(); 00108 00109 private: 00110 void remove(msg_list_t *l, msg_list_t *p); 00111 00112 msg_list_t *__list; 00113 msg_list_t *__end_el; 00114 Mutex *__mutex; 00115 }; 00116 00117 00118 /** Check if message is of given type. 00119 * The current message is checked if it is of the type that the 00120 * template parameter determines. Use non-pointer template arguments! 00121 * @return true, if the current message is of the given type, false otherwise 00122 */ 00123 template <class MessageType> 00124 bool 00125 MessageQueue::MessageIterator::is() const 00126 { 00127 MessageType *msg = dynamic_cast<MessageType *>(cur->msg); 00128 return ( msg != 0 ); 00129 } 00130 00131 00132 /** Get current message of given type. 00133 * This will return the current message of the given template type. An TypeMismatchException 00134 * is thrown if the current message is not of the requested type. 00135 * @exception TypeMismatchException thrown, if current message is not of requested type. 00136 * @return current message of requested type 00137 */ 00138 template <class MessageType> 00139 MessageType * 00140 MessageQueue::MessageIterator::get() const 00141 { 00142 MessageType *msg = dynamic_cast<MessageType *>(cur->msg); 00143 if ( msg == 0 ) { 00144 throw TypeMismatchException("Message types do not match (get)"); 00145 } 00146 return msg; 00147 } 00148 00149 } // end namespace fawkes 00150 00151 #endif