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 |