message.h
00001 /*
00002  *  Player - One Hell of a Robot Server
00003  *  Copyright (C) 2000
00004  *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
00005  *
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  */
00022 /********************************************************************
00023  *
00024  *  This library is free software; you can redistribute it and/or
00025  *  modify it under the terms of the GNU Lesser General Public
00026  *  License as published by the Free Software Foundation; either
00027  *  version 2.1 of the License, or (at your option) any later version.
00028  *
00029  *  This library is distributed in the hope that it will be useful,
00030  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00031  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00032  *  Lesser General Public License for more details.
00033  *
00034  *  You should have received a copy of the GNU Lesser General Public
00035  *  License along with this library; if not, write to the Free Software
00036  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00037  *
00038  ********************************************************************/
00039 
00040 /*
00041  * Desc: Message class and message queues
00042  * CVS:  $Id: message.h 8004 2009-07-13 14:03:44Z thjc $
00043  * Author: Toby Collett - Jan 2005
00044  */
00045 
00046 #ifndef MESSAGE_H
00047 #define MESSAGE_H
00048 
00049 #if defined (WIN32)
00050   #if defined (PLAYER_STATIC)
00051     #define PLAYERCORE_EXPORT
00052   #elif defined (playercore_EXPORTS)
00053     #define PLAYERCORE_EXPORT    __declspec (dllexport)
00054   #else
00055     #define PLAYERCORE_EXPORT    __declspec (dllimport)
00056   #endif
00057 #else
00058   #define PLAYERCORE_EXPORT
00059 #endif
00060 
00061 #include <pthread.h>
00062 
00063 #include <libplayerinterface/player.h>
00064 
00065 class MessageQueue;
00066 
00073 class PLAYERCORE_EXPORT QueuePointer
00074 {
00075   public:
00077     QueuePointer();
00079     QueuePointer(bool _Replace, size_t _Maxlen);
00081         ~QueuePointer();
00083         QueuePointer(const QueuePointer & CopyFrom);
00084         
00086         QueuePointer & operator = (const QueuePointer & rhs);
00088         MessageQueue * operator -> ();
00090         MessageQueue * get() const;
00092         MessageQueue & operator * ();
00094         bool operator == (const QueuePointer & rhs);
00096         bool operator == (void * pointer);
00098         bool operator != (const QueuePointer & rhs);
00100         bool operator != (void * pointer);
00101         
00102   private:
00104     void DecRef();
00105 
00107     MessageQueue * Queue;
00108 
00110     unsigned int * RefCount;
00111 
00113     pthread_mutex_t * Lock;
00114 };
00115 
00116 
00117 
00132 class PLAYERCORE_EXPORT Message
00133 {
00134   public:
00137     Message(const struct player_msghdr & Header,
00138             void* data,
00139             bool copy = true);
00140 
00143     Message(const struct player_msghdr & Header,
00144             void* data,
00145             QueuePointer &_queue,
00146             bool copy = true);
00147 
00149     Message(const Message & rhs);
00150 
00152     ~Message();
00153 
00159     static bool MatchMessage(player_msghdr_t* hdr,
00160                              int type,
00161                              int subtype,
00162                              player_devaddr_t addr)
00163     {
00164       return(((type < 0) || (hdr->type == (uint8_t)type)) &&
00165              ((subtype < 0) || (hdr->subtype == (uint8_t)subtype)) &&
00166              (hdr->addr.host == addr.host) &&
00167              (hdr->addr.robot == addr.robot) &&
00168              (hdr->addr.interf == addr.interf) &&
00169              (hdr->addr.index == addr.index));
00170     }
00171 
00177     static bool MatchMessage(player_msghdr_t* hdr,
00178                              int type,
00179                              int subtype)
00180     {
00181       return(((type < 0) || (hdr->type == (uint8_t)type)) &&
00182              ((subtype < 0) || (hdr->subtype == (uint8_t)subtype)));
00183     }    
00184     
00186     player_msghdr_t * GetHeader() {return &Header;};
00188     void* GetPayload() {return (void*)Data;};
00190     unsigned int GetDataSize() {return Header.size;};
00192     bool Compare(Message &other);
00194     void DecRef();
00195 
00197     QueuePointer Queue;
00198 
00200     unsigned int * RefCount;
00201 
00202   private:
00203     void CreateMessage(const struct player_msghdr & Header,
00204             void* data,
00205             bool copy = true);
00206           
00208     player_msghdr_t Header;
00210     uint8_t * Data;
00212     pthread_mutex_t * Lock;
00213 };
00214 
00218 class PLAYERCORE_EXPORT MessageQueueElement
00219 {
00220   public:
00222     MessageQueueElement();
00224     ~MessageQueueElement();
00225 
00227     Message* msg;
00228   private:
00230     MessageQueueElement * prev;
00232     MessageQueueElement * next;
00233 
00234     friend class MessageQueue;
00235 };
00236 
00243 class PLAYERCORE_EXPORT MessageReplaceRule
00244 {
00245   private:
00246     // The address to match (not using a player_devaddr_t so that we can
00247     // use -1 to indicate don't care)
00248     int host, robot, interf, index;
00249     // The type and subtype to match (-1 is don't care)
00250     int type, subtype;
00251   public:
00252     MessageReplaceRule(int _host, int _robot, int _interf, int _index,
00253                        int _type, int _subtype, int _replace) :
00254             host(_host), robot(_robot), interf(_interf), index(_index),
00255             type(_type), subtype(_subtype), replace(_replace), next(NULL) {}
00256 
00257     bool Match(player_msghdr_t* hdr)
00258     {
00259       return(((this->host < 0) ||
00260               ((uint32_t)this->host == hdr->addr.host)) &&
00261              ((this->robot < 0) ||
00262               ((uint32_t)this->robot == hdr->addr.robot)) &&
00263              ((this->interf < 0) ||
00264               ((uint16_t)this->interf == hdr->addr.interf)) &&
00265              ((this->index < 0) ||
00266               ((uint16_t)this->index == hdr->addr.index)) &&
00267              ((this->type < 0) ||
00268               ((uint8_t)this->type == hdr->type)) &&
00269              ((this->subtype < 0) ||
00270               ((uint8_t)this->subtype == hdr->subtype)));
00271     }
00272 
00273     bool Equivalent (int _host, int _robot, int _interf, int _index, int _type, int _subtype)
00274     {
00275       return (host == _host && robot == _robot && interf ==_interf && index == _index &&
00276           type == _type && subtype == _subtype);
00277     }
00278 
00279     // To replace, or not to replace
00280     // That is the question
00281     int replace;
00282     // Next rule in the list
00283     MessageReplaceRule* next;
00284 };
00285 
00337 class PLAYERCORE_EXPORT MessageQueue
00338 {
00339   public:
00341     MessageQueue(bool _Replace, size_t _Maxlen);
00343     ~MessageQueue();
00345     bool Empty() { return(this->head == NULL); }
00348     bool Push(Message& msg);
00349 
00354     void PushFront(Message & msg, bool haveLock);
00355 
00360     void PushBack(Message & msg, bool haveLock);
00361 
00365     Message* Pop();
00369     void SetReplace(bool _Replace) { this->Replace = _Replace; };
00376     void AddReplaceRule(int _host, int _robot, int _interf, int _index,
00377                         int _type, int _subtype, int _replace);
00383     void AddReplaceRule(const player_devaddr_t &device,
00384                         int _type, int _subtype, int _replace);
00387     int CheckReplace(player_msghdr_t* hdr);
00394     bool Wait(double TimeOut=0.0);
00397     void DataAvailable(void);
00399     bool Filter(Message& msg);
00401     void ClearFilter(void);
00403     void SetFilter(int host, int robot, int interf, int index,
00404                    int type, int subtype);
00406     void SetPull (bool _pull) { this->pull = _pull; }
00407 
00409     size_t GetLength(void);
00410 
00412     void SetDataRequested(bool d, bool haveLock);
00413 
00414   private:
00416     void Lock() {pthread_mutex_lock(&lock);};
00418     void Unlock() {pthread_mutex_unlock(&lock);};
00421     void Remove(MessageQueueElement* el);
00423     MessageQueueElement* head;
00425     MessageQueueElement* tail;
00427     pthread_mutex_t lock;
00429     size_t Maxlen;
00431     MessageReplaceRule* replaceRules;
00434     bool Replace;
00436     size_t Length;
00440     pthread_cond_t cond;
00442     pthread_mutex_t condMutex;
00444     bool filter_on;
00445     int filter_host, filter_robot, filter_interf,
00446         filter_index, filter_type, filter_subtype;
00449     bool pull;
00452     bool data_requested;
00454     bool data_delivered;
00456     bool drop_count;
00457 };
00458 
00459 
00460 
00461 
00462 #endif