Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phLiveObject.h

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission 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 Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifndef _PHLIVEOBJECT_H
00027 #define _PHLIVEOBJECT_H
00028 
00029 #include <phStdint.h>
00030 #include <phRWLock.h>
00031 #include <phSemaphore.h>
00032 #include <phTimeInterval.h>
00033 #include <phConditionCounter.h>
00034 
00041 /* ---------------------------------------------------------------------- */
00042 /* Read Write macros for 'this' */
00043 /* ---------------------------------------------------------------------- */
00044 #define phTHIS_READLOCK_LOOSE(l) \
00045     rc = this->readLock(); \
00046     phPRINT_RC(rc,NULL,"this->readLock()"); \
00047     if (rc == phSUCCESS) ++l;
00048 
00049 #define phTHIS_READLOCK(l) \
00050     rc = this->readLock(); \
00051     phCHECK_RC(rc,NULL,"this->readLock()"); \
00052     ++l;
00053 
00054 #define phTHIS_WRITELOCK_LOOSE(l) \
00055     rc = this->writeLock(); \
00056     phPRINT_RC(rc,NULL,"this->writeLock()"); \
00057     if (rc == phSUCCESS) ++l;
00058 
00059 #define phTHIS_WRITELOCK(l) \
00060     rc = this->writeLock(); \
00061     phCHECK_RC(rc,NULL,"this->writeLock()"); \
00062     ++l;
00063 
00064 #define phTHIS_RWUNLOCK_LOOSE(l) \
00065     if (l > 0) \
00066     { \
00067         rc = this->rwUnlock(); \
00068         phPRINT_RC(rc,NULL,"this->rwUnlock()"); \
00069         if (rc == phSUCCESS) --l; \
00070     }
00071 
00072 #define phTHIS_RWUNLOCK(l) \
00073     if (l > 0) \
00074     { \
00075         rc = this->rwUnlock(); \
00076         --l; \
00077         phCHECK_RC(rc,NULL,"this->rwUnlock()"); \
00078     }
00079 
00080 #define phTHIS_RWUNLOCK_ERROR(l) \
00081     if (l > 0) \
00082     { \
00083         do { \
00084             rc = this->rwUnlock(); \
00085             phPRINT_RC(rc,NULL,"this->rwUnlock()"); \
00086             if (rc == phSUCCESS) --l; \
00087         } while ((l > 0) && (rc == phSUCCESS)); \
00088     }
00089     
00090 #define phTHIS_RWUNLOCK_RET(l,success_value,error_value)    \
00091     phTHIS_RWUNLOCK(l);                                     \
00092     return success_value;                                   \
00093 error:                                                      \
00094     phTHIS_RWUNLOCK_ERROR(l);                               \
00095     return error_value;         
00096 
00097 /* ---------------------------------------------------------------------- */
00098 /* Read Write Macros for the phLiveObject inherited classes*/
00099 /* ---------------------------------------------------------------------- */
00100 /* These operate on any read/write lock */
00101 /* ---------------------------------------------------------------------- */
00102 #define phREADLOCK(rw,l) \
00103     rc = rw.readLock(); \
00104     phCHECK_RC(rc,NULL,"rw.readLock()"); \
00105     ++l; \
00106 
00107 #define phREADLOCK_LOOSE(rw,l) \
00108     rc = rw.readLock(); \
00109     phPRINT_RC(rc,NULL,"rw.readLock()"); \
00110     if (rc == phSUCCESS) ++l; \
00111 
00112 #define phWRITELOCK(rw,l) \
00113     rc = rw.writeLock(); \
00114     phCHECK_RC(rc,NULL,"rw.writeLock()"); \
00115     ++l; \
00116 
00117 #define phWRITELOCK_LOOSE(rw,l) \
00118     rc = rw.writeLock(); \
00119     phPRINT_RC(rc,NULL,"rw.writeLock()"); \
00120     if (rc == phSUCCESS) ++l; \
00121 
00122 #define phRWUNLOCK(rw,l) \
00123     if (l > 0) \
00124     { \
00125         rc = rw.rwUnlock(); \
00126         --l; \
00127         phCHECK_RC(rc,NULL,"rw.rwUnlock()"); \
00128     }
00129 
00130 #define phRWUNLOCK_LOOSE(rw,l) \
00131     if (l > 0) \
00132     { \
00133         rc = rw.rwUnlock(); \
00134         phPRINT_RC(rc,NULL,"rw.rwUnlock()"); \
00135         if (rc == phSUCCESS) --l; \
00136     }
00137 
00138 #define phRWUNLOCK_ERROR(rw,l) \
00139     if (l > 0) \
00140     { \
00141         do { \
00142             rc = rw.rwUnlock(); \
00143             phPRINT_RC(rc,NULL,"rw.rwUnlock()"); \
00144             if (rc == phSUCCESS) --l; \
00145         } while ((l > 0) && (rc == phSUCCESS)); \
00146     }
00147 
00148 /* ---------------------------------------------------------------------- */
00149 /* Yea, the names are "wicked" long, but you won't have to guess what they
00150  * mean. Stop complaining about the carpal tunnel! */
00151 /* ---------------------------------------------------------------------- */
00152 #define phLiveCookieNOFLAG  phSemNOFLAG /*(0)*/
00153 #define phLiveCookieNOWAIT  phSemNOWAIT /*(1<<0)*/
00154 #define phLiveCookieWAIT    phSemWAIT   /*(1<<1)*/ /* default */
00155 
00156 /* ---------------------------------------------------------------------- */
00157 #define phLiveObjectNOFLAG  (0)
00158 
00161 #define phLiveObjectNOWAIT  (1<<0)
00162 
00163 #define phLiveObjectWAIT    (1<<1) /* default */
00164 
00166 #define phLiveObjectCOPY    (1<<2) /* default */
00167 
00171 #define phLiveObjectSWAP    (1<<3)
00172 
00179 #define phLiveObjectFORCE   (1<<4) /* force an update */
00180 
00181 /* ---------------------------------------------------------------------- */
00182 #define phLiveCookieNOTAKE      phSemaphoreNOTAKE
00183 #define phLiveCookieTAKEN       phSemaphoreTAKEN
00184 
00185 #define phLiveObjectNOUPDATE    phSemaphoreNOTAKE
00186 #define phLiveObjectUPDATED     0
00187 
00188 /* ---------------------------------------------------------------------- */
00189 #define phLiveObjectDEFAULTFLAGS    (phLiveObjectWAIT | phLiveObjectCOPY)
00190 
00191 #define phLiveObjectTRANSFERMASK    (phLiveObjectCOPY | phLiveObjectSWAP)
00192 #define phLiveObjectWAITMASK        (phLiveObjectWAIT | phLiveObjectNOWAIT)
00193 
00194 #define phLiveObjectFLAGMASK \
00195     (phLiveObjectNOWAIT | phLiveObjectSWAP | \
00196      phLiveObjectWAIT   | phLiveObjectCOPY)
00197  /* end \addtogroup PhissionSystem */
00199 
00200 /* ---------------------------------------------------------------------- */
00201 PHAPI(class) phLiveObject;
00207 PHAPI(class) phLiveCookie : public phSemaphore
00208 {
00209 protected:
00210     uint32_t        m_cookie_key;
00211     
00212     int32_t         m_jitter_us;
00213     phTimeInterval  m_jitter;
00214     phMutex         m_jitter_lock;
00215 
00216     phLiveCookie   *m_cookie_next;
00217     phLiveCookie   *m_cookie_prev;
00218 
00219     phSemaphore     m_wakeup;
00220     
00221     phLiveObject   *m_owner;
00222     
00223 public:
00224 
00225     phLiveCookie();
00226     ~phLiveCookie();
00227     
00228     int             setOwner    ( phLiveObject *object );
00229     phLiveObject    *getOwner   ();
00230     int             setKey      ( uint32_t k );
00231     uint32_t        getKey      ();
00232 
00233     /* specialize 'take' to allow ignoring of a semaphore posted from
00234      * a different entity than the source or when an update didn't
00235      * really occur but we want the cookie to return from take */
00236     int             take        ( uint32_t flag = phSemaphoreWAIT );
00237     int             wakeup      ();
00238     
00239     int             postCookie  ();
00240     
00241     int             setJitter   ( int32_t jitter );
00242     int32_t         getJitter   ();
00243     
00244     int             setNext     ( phLiveCookie *n );
00245     int             setPrev     ( phLiveCookie *p );
00246     phLiveCookie   *getNext     ();
00247     phLiveCookie   *getPrev     ();
00248 };
00249 
00250 /* ---------------------------------------------------------------------- */
00263 PHAPI(class) phLiveObject : public phMutex 
00264 {
00265 private:
00266     /* LiveClient support */
00267     phLiveCookie   *m_cookie;
00268     phLiveObject   *m_source_object;
00269     uint32_t        m_connected;
00270     uint32_t        m_flags;
00271     phMutex         m_updateLock;
00272 
00273     phRWLock        m_accessLock;
00274 
00275     /* LiveSource support */
00276     phMutex         m_cookie_mutex;
00277     uint32_t        m_cookie_count;
00278     phLiveCookie   *m_cookie_head;
00279     phLiveCookie   *m_cookie_tail;
00280     uint32_t        m_source_object_key;
00281 #if 0
00282     uint32_t        m_reading_clients;
00283 #endif
00284     phConditionCounter *m_waiting_var;
00285 
00286     phTimeInterval  m_notify_jitter;
00287     phMutex         m_notify_jitter_lock;
00288     int32_t         m_notify_jitter_us;
00289     int32_t         m_notify_jitter_avg;
00290     int32_t         m_notify_jitter_samples;
00291 
00292     phRWLock        m_client_jitter_rwlock;
00293     int32_t         m_client_jitter_us;
00294     int32_t         m_client_jitter_avg;
00295     int32_t         m_client_jitter_samples;
00296      
00297     /* Using the m_flags, create a new flag mask if
00298      * there are new flags passed to a method */
00299     /* gets m_flags and factors with flags that were 
00300      * potentially passed as arguments */
00301     uint32_t    factorFlags( uint32_t newflags );
00302     
00303     /* ---------------------------------------------- */
00304     /* phLiveObject source setup / teardown */
00305     /* These are called source_* cause I was getting
00306      * confused by the method names. That was reason
00307      * enough. */
00308     /* ---------------------------------------------- */
00309     int source_connect      ( phLiveObject *client,
00310                               phLiveCookie **cookie );
00311     int source_disconnect   ( phLiveCookie **cookie );
00312     int source_update       ( phObject     *object, 
00313                               phLiveCookie *cookie,
00314                               uint32_t      flags = phLiveObjectNOFLAG );
00315 
00316     /* This is the actual method to set m_source_object */
00317     int setSourceObject( phLiveObject *sourceObject );
00318         
00319 protected:
00320     int m_swap_disabled;
00321     
00322     int m_notify_disabled;
00323 
00324     /* force allows overriding the m_notify_disabled value check
00325      * within notify. force will make notify to signal all listening 
00326      * clients */
00327     int notify(int force = 0);
00328 
00329 public:
00330     phLiveObject();
00331     virtual ~phLiveObject();
00332 
00359     void disableSwap    ( int disable = 1 );
00360     void enableSwap     ( int enable  = 1 );
00361     int isSwapDisabled  ();
00362     int isSwapEnabled   ();
00363     
00364     /* Notify: listening/connected and waiting objects
00365      * are notified of a change in the object's data only
00366      * when notify is enabled */
00367     void    disableNotify       ( int disable = 1 );
00368     void    enableNotify        ( int enable  = 1 );
00369     int     isNotifyDisabled    ();
00370     int     isNotifyEnabled     ();
00371     
00372     int     resetJitter();
00373     
00374     /* jitter values in microseconds/us */
00375     int     resetNotifyJitter           ();
00376     int     setNotifyJitter             ( int32_t jitter );
00377     int32_t getNotifyJitter             ();
00378     int     setNotifyJitterAvg          ( int32_t jitter_avg );
00379     int32_t getNotifyJitterAvg          ();
00380     int     setNotifyJitterAvgSamples   ( int32_t jitter_samples );
00381     int32_t getNotifyJitterAvgSamples   ();
00382 
00383     /* If you're using client jitter, make sure you reset it before the 
00384        loop that uses it; The value is persistent throughout the existence
00385        of the object */
00386     int     resetClientJitter           ();
00387     int     setClientJitter             ( int32_t jitter );
00388     int32_t getClientJitter             ();
00389     int     setClientJitterAvg          ( int32_t jitter_avg );
00390     int32_t getClientJitterAvg          ();
00391     int     setClientJitterAvgSamples   ( int32_t jitter_samples );
00392     int32_t getClientJitterAvgSamples   ();
00393 
00394     phConditionCounter *getWaitingCounter();
00395 
00396     /* ---------------------------------------------- */
00397     /* phLiveObject client setup / teardown */
00398     /* ---------------------------------------------- */
00399     /* connect flags are perminent during the connection's
00400      * lifetime. */
00401     int connect     ( phLiveObject *obj,
00402                       uint32_t      flags = phLiveObjectNOFLAG );
00403     int disconnect();
00404 
00405     int wakeup_clients();
00406     int wakeup_self();
00407 
00431     int update(uint32_t flags = phLiveObjectNOFLAG );
00432     
00440     int      setFlags(uint32_t flags);
00441     uint32_t getFlags();
00442 
00443     int isConnected();
00444 
00445     /* --------------------------------------------------------------------- */
00453     int release_clients();
00454 
00455     /* ---------------------------------------------- */
00456     /* ReadWrite Lock support for derived classes   
00457      * This was added to remove the multiple inheritance
00458      * in phDataObject to support Java. 
00459      * I hate doing this, but it's the only way to
00460      * do multiple inheritence without multiple inheritence.
00461      */
00462     /* ---------------------------------------------- */
00463     int readLock    ();
00464     int tryReadLock ();
00465     int writeLock   ();
00466     int tryWriteLock();
00467     int rwUnlock    ();
00468 
00469     int hasClients  ();
00470     int clientCount ();
00471 };
00472 
00473 #endif /* _PHLIVEOBJECT_H */




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:02 2007 for phission by  doxygen 1.4.4