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

phRWLock.cpp

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 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00033     #include <pthread.h>
00034     #if defined(HAVE_ERRNO_H)
00035         #include <errno.h>
00036     #endif
00037 #endif
00038 #if defined(HAVE_UNISTD_H)
00039     #include <unistd.h>
00040 #endif
00041 #if defined(WIN32)
00042     #include <windows.h>
00043 #endif
00044 
00045 #include <phObject.h>
00046 #include <phMutex.h>
00047 
00048 #include <phRWLock.h>
00049 
00050 #if defined(__ADSPBLACKFIN__)
00051     #include <phCondition.h>
00052     #include <phConditionCounter.h>
00053 #endif
00054 
00055 #include <phError.h>
00056 #include <phMemory.h>
00057 #include <phPrint.h>
00058 
00059 #define RECURSIVE_SUPPORT() 1
00060 
00061 #define phRWLock_INVALIDOWNER ((uintmax_t)-1)
00062 
00063 /* ---------------------------------------------------------------------- */
00064 struct ph_rwlock_info_t
00065 {
00066     /* rw == reader_writer */
00067 #if defined(WIN32)
00068     HANDLE  m_rw_access_event;
00069     HANDLE  m_reader_event;
00070     HANDLE  m_writer_mutex;
00071     LONG    m_reader_counter;
00072 #endif
00073 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00074     pthread_rwlock_t    m_rwlock;
00075 #endif
00076 #if defined(__ADSPBLACKFIN__)
00077     /* reader_event: signaled by the first reader, waited on by everyone
00078      * else */
00079     phCondition *m_reader_event;
00080     uint32_t    m_reader_event_value;
00081 
00082     /* rw_access_event: signaled by a writer or last reader;
00083      * provides access to the data for either readers or a writer */
00084     phCondition *m_rw_access_event;
00085     uint32_t    m_rw_access_event_value;
00086     
00087     /* writer_mutex: provides exclusive access to the writer code, only
00088      * one writer is accessing at a time */
00089     phMutex     *m_writer_mutex;
00090 
00091     /* reader_counter: atomically access count readers as they come
00092      * through */
00093     phMutex     *m_reader_counter_mutex;
00094     int32_t     m_reader_counter;
00095 #endif
00096 };
00097 
00098 /* ---------------------------------------------------------------------- */
00099 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00100 static int rwlock_error(int err_rc, const char *rwlock_func )
00101 {
00102     phFUNCTION("rwlock_error")
00103     
00104     char *err_msg = NULL;
00105     char *err = NULL;
00106 
00107     if (err_rc == 0) goto success;
00108     
00109     phCHECK_NULLPTR(rwlock_func,NULL,"Invalid rwlock_func argument");
00110     
00111     if (strcmp(rwlock_func,"pthread_rwlock_init") == 0)
00112     {
00113         if (err_rc == EAGAIN)
00114         {
00115             err = "EAGAIN";
00116             err_msg = "The system lacked the necessary resources (other than memory) to initialize another read-write lock.";
00117         }
00118         else if (err_rc == EBUSY)
00119         {
00120             err = "EBUSY";
00121             err_msg = "The implementation has detected an attempt to reinitialize the object referenced by rwlock, a previously initialized but not yet destroyed read-write lock.";
00122         }
00123         else if (err_rc == ENOMEM)
00124         {
00125             err = "ENOMEM";
00126             err_msg = "Insufficient memory exists to initialize the read-write lock.";
00127         }
00128         else if (err_rc == EPERM)
00129         {
00130             err = "EPERM";
00131             err_msg = "The caller does not have the privilege to perform the operation.";
00132         }
00133         else if (err_rc == EINVAL)
00134         {
00135             err = "EINVAL";
00136             err_msg = "The value specified by attr is invalid.";
00137         }
00138     }
00139     else if (strcmp(rwlock_func,"pthread_rwlock_destroy") == 0)
00140     {
00141         if (err_rc == EBUSY)
00142         {
00143             err = "EBUSY";
00144             err_msg = "The implementation has detected an attempt to destroy the object referenced by rwlock while it is locked.";
00145         }
00146         else if (err_rc == EINVAL)
00147         {
00148             err = "EINVAL";
00149             err_msg = "The value specified by rwlock is invalid.";
00150         }
00151     }
00152     else if (strcmp(rwlock_func,"pthread_rwlock_timedrdlock") == 0)
00153     {
00154         if (err_rc == ETIMEDOUT)
00155         {
00156             err = "ETIMEDOUT";
00157             err_msg = "The lock could not be acquired before the specified timeout expired.";
00158         }
00159         else if (err_rc == EAGAIN)
00160         {
00161             err = "EAGAIN";
00162             err_msg = "The read lock could not be acquired because the maximum number of read locks for lock would be exceeded.";
00163         }
00164         else if (err_rc == EDEADLK)
00165         {
00166             err = "EDEADLK";
00167             err_msg = "A deadlock condition was detected or the calling thread already holds a write lock on rwlock.";
00168         }
00169         else if (err_rc == EINVAL)
00170         {
00171             err = "EINVAL";
00172             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object, or the abs_timeout nanosecond value is less than zero or greater than or equal to 1000 million.";
00173         }
00174     }
00175     else if (strcmp(rwlock_func,"pthread_rwlock_rdlock") == 0)
00176     {
00177         if (err_rc == EINVAL)
00178         {
00179             err = "EINVAL";
00180             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object.";
00181         }
00182         else if (err_rc == EAGAIN)
00183         {
00184             err = "EAGAIN";
00185             err_msg = "The read lock could not be acquired because the maximum number of read locks for rwlock has been exceeded.";
00186         }
00187         else if (err_rc == EDEADLK)
00188         {
00189             err = "EDEADLK";
00190             err_msg = "A deadlock condition was detected or the current thread already owns the read-write lock for writing.";
00191         }
00192     }
00193     else if (strcmp(rwlock_func,"pthread_rwlock_tryrdlock") == 0)
00194     {
00195         if (err_rc == EBUSY)
00196         {
00197             err = "EBUSY";
00198             err_msg = "The read-write lock could not be acquired for reading because a writer holds the lock or a writer with the appropriate priority was blocked on it.";
00199         }
00200         else if (err_rc == EINVAL)
00201         {
00202             err = "EINVAL";
00203             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object.";
00204         }
00205         else if (err_rc == EAGAIN)
00206         {
00207             err = "EAGAIN";
00208             err_msg = "The read lock could not be acquired because the maximum number of read locks for rwlock has been exceeded.";
00209         }
00210     }
00211     else if (strcmp(rwlock_func,"pthread_rwlock_timedwrlock") == 0)
00212     {
00213         if (err_rc == ETIMEDOUT)
00214         {
00215             err = "ETIMEDOUT";
00216             err_msg = "The lock could not be acquired before the specified timeout expired.";
00217         }
00218         else if (err_rc == EDEADLK)
00219         {
00220             err = "EDEADLK";
00221             err_msg = "A deadlock condition was detected or the calling thread already holds the rwlock.";
00222         }
00223         else if (err_rc == EINVAL)
00224         {
00225             err = "EINVAL";
00226             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object, or the abs_timeout nanosecond value is less than zero or greater than or equal to 1000 million.";
00227         }
00228     }
00229     else if (strcmp(rwlock_func,"pthread_rwlock_wrlock") == 0)
00230     {
00231         if (err_rc == EINVAL)
00232         {
00233             err = "EINVAL";
00234             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object.";
00235         }
00236         else if (err_rc == EDEADLK)
00237         {
00238             err = "EDEADLK";
00239             err_msg = "A deadlock condition was detected or the current thread already owns the read-write lock for writing or reading.";
00240         }
00241     }
00242     else if (strcmp(rwlock_func,"pthread_rwlock_trywrlock") == 0)
00243     {
00244         if (err_rc == EBUSY)
00245         {
00246             err = "EBUSY";
00247             err_msg = "The read-write lock could not be acquired for writing because it was already locked for reading or writing.";
00248         }
00249         else if (err_rc == EINVAL)
00250         {
00251             err = "EINVAL";
00252             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object.";
00253         }
00254     }
00255     else if (strcmp(rwlock_func,"pthread_rwlock_unlock") == 0)
00256     {
00257         if (err_rc == EINVAL)
00258         {
00259             err = "EINVAL";
00260             err_msg = "The value specified by rwlock does not refer to an initialized read-write lock object.";
00261         }
00262         if (err_rc == EPERM)
00263         {
00264             err = "EPERM";
00265             err_msg = "The current thread does not hold a lock on the read-write lock.";
00266         }
00267     }
00268     
00269     fprintf(stderr,
00270            "(pid:%d|thread:%d:%p) %s[%s]:%s\n",
00271            getpid(),
00272            (int)phGetCurrentThreadId(),
00273            (void *)phGetCurrentThreadId(),
00274            (rwlock_func == NULL) ? "" : rwlock_func,
00275            (err == NULL) ? "" : err,
00276            (err_msg == NULL) ? "" : err_msg );
00277 
00278     fflush(stderr);
00279 
00280 success:
00281     return phSUCCESS;
00282 error:
00283     return phFAIL;
00284 }
00285 #endif /* WIN32 */
00286 
00287 /* ---------------------------------------------------------------------- */
00288 /* ---------------------------------------------------------------------- */
00289 void phRWLock::init_lock()
00290 {
00291     phFUNCTION("phRWLock::init_lock")
00292     int prc = 0;
00293    
00294 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00295     /* int   pthread_rwlock_init(   pthread_rwlock_t *,
00296      *                              const pthread_rwlockattr_t *); */
00297     /* initialize the rwlock */
00298     /* The rwlock is a read-recursive type lock by definition */
00299     
00300     prc = rc = pthread_rwlock_init(&(this->m_info->m_rwlock),NULL);
00301     phPRINT_RC(rc,"pthread_rwlock_init",
00302             "this->m_info->m_rwlock init failed");
00303     rwlock_error(rc,"pthread_rwlock_init");
00304 #endif /* WIN32 */
00305 
00306 #if defined(WIN32)
00307     
00308     this->m_info->m_reader_event        = CreateEvent( NULL, TRUE, FALSE, NULL );
00309     phPRINT_NULLPTR(  this->m_info->m_reader_event,
00310                     "CreateEvent",
00311                     "CreateEvent failed: this->m_info->m_reader_event." );
00312     
00313     this->m_info->m_rw_access_event = CreateEvent( NULL, FALSE, TRUE, NULL );
00314     phPRINT_NULLPTR(  this->m_info->m_rw_access_event,
00315                     "CreateEvent",
00316                     "CreateEvent failed: this->m_info->m_rw_access_event." );
00317     
00318     this->m_info->m_writer_mutex        = CreateMutex( NULL, FALSE, NULL );
00319     phPRINT_NULLPTR(  this->m_info->m_writer_mutex,
00320                     "CreateMutex",
00321                     "CreateMutex failed: this->m_info->m_writer_mutex." );
00322 #endif
00323 
00324 #if defined(__ADSPBLACKFIN__)
00325     this->m_info->m_writer_mutex            = new phMutex();
00326     this->m_info->m_reader_counter_mutex    = new phMutex();
00327     this->m_info->m_reader_event            = new phCondition();
00328     this->m_info->m_reader_event_value      = 0;
00329     this->m_info->m_rw_access_event         = new phCondition();
00330     this->m_info->m_rw_access_event_value   = 1;
00331 #endif
00332 
00333 #if defined(WIN32) || defined(__ADSPBLACKFIN__)
00334     this->m_info->m_reader_counter        = -1;
00335 #endif
00336 
00337     rc = this->writeLock();
00338     phPRINT_RC(rc,NULL,"this->writeLock()");
00339 }
00340 
00341 /* ---------------------------------------------------------------------- */
00342 phRWLock::phRWLock()
00343 { 
00344     phFUNCTION("phRWLock::phRWLock")
00345     int locked  = 0;
00346 
00347     phMUTEX_LOOSE_LOCK(this->m_mutex,locked);
00348 
00349     this->setName("phRWLock");
00350     
00351     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00352 
00353     this->m_readers         = 0;
00354     this->m_writer_nlocks   = 0;
00355     this->m_writer          = phRWLock_INVALIDOWNER;
00356     this->m_info            = (struct ph_rwlock_info_t *)phCalloc(1,
00357                                         sizeof(struct ph_rwlock_info_t));
00358     phPRINT_PTR(this->m_info,"phCalloc","phCalloc failed.");
00359     
00360     this->init_lock();
00361 
00362     rc = this->rwUnlock();
00363     phPRINT_RC(rc,NULL,"this->rwUnlock()");
00364 
00365     phMUTEX_LOOSE_UNLOCK(this->m_mutex,locked);
00366 } 
00367 
00368 /* ---------------------------------------------------------------------- */
00369 phRWLock::~phRWLock() 
00370 { 
00371     phFUNCTION("phRWLock::~phRWLock")
00372     int prc     = 0;
00373     int locked  = 0;
00374 #if defined(WIN32)
00375     BOOL bResult= TRUE;
00376 #endif
00377     
00378     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00379     
00380     phMUTEX_LOOSE_LOCK(this->m_mutex,locked);
00381     
00382 #if RECURSIVE_SUPPORT()  
00383     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00384     
00385     if (this->m_writer != phRWLock_INVALIDOWNER)
00386     {
00387         /* if this isn't the owning thread, then return an 
00388          * error */
00389         DEBUG_PRINT("(this:%p)\tphTHREADS_EQUAL(self:%ld,writer:%ld))\n",
00390                      this,phGetCurrentThreadId(),this->m_writer);
00391         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
00392         {
00393             while (this->m_writer_nlocks > 0)
00394             {
00395                 rc = this->rwUnlock();
00396                 phPRINT_RC(rc,NULL,"this->rwUnlock()");
00397                 DEBUG_PRINT("(this:%p)\tnlocks:%u\n",this,this->m_writer_nlocks);
00398             }    
00399         }
00400     }
00401 
00402     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00403 #endif
00404  
00405 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00406     /* destroy the lock */
00407     /* int   pthread_rwlock_destroy(pthread_rwlock_t *); */
00408     prc = rc = pthread_rwlock_destroy(&(this->m_info->m_rwlock));
00409     phPRINT_RC(rc,"pthread_rwlock_destroy","destroying rwlock failed");
00410     if (prc != EBUSY) rwlock_error(rc,"pthread_rwlock_destroy");
00411 
00412     phMemset(&this->m_info->m_rwlock,0,sizeof(pthread_rwlock_t));
00413 #endif
00414 
00415 #if defined(WIN32)
00416     bResult = CloseHandle(this->m_info->m_reader_event);
00417     if (!bResult) rc = phFAIL; else rc = phSUCCESS;
00418     phPRINT_RC(rc,"CloseHandle","CloseHandle failed: this->m_info->m_reader_event \n");
00419     
00420     bResult = CloseHandle(this->m_info->m_rw_access_event);
00421     if (!bResult) rc = phFAIL; else rc = phSUCCESS;
00422     phPRINT_RC(rc,"CloseHandle","CloseHandle failed: this->m_info->m_rw_access_event \n");
00423     
00424     bResult = CloseHandle(this->m_info->m_writer_mutex);
00425     if (!bResult) rc = phFAIL; else rc = phSUCCESS;
00426     phPRINT_RC(rc,"CloseHandle","CloseHandle failed: this->m_info->m_writer_mutex \n");
00427 #endif
00428 
00429 #if defined(__ADSPBLACKFIN__)
00430     phDelete(this->m_info->m_writer_mutex);
00431     phDelete(this->m_info->m_reader_counter_mutex);
00432     phDelete(this->m_info->m_reader_event);
00433     phDelete(this->m_info->m_rw_access_event);
00434 #endif
00435 
00436     /* Lock the object while it's being deleted */
00437     /* The OS should release other objects when the phMutex object is 
00438      * finally destroyed */
00439     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00440 
00441     phFree(this->m_info);
00442 } 
00443 
00444 /* ---------------------------------------------------------------------- */
00445 int phRWLock::readLock() 
00446 { 
00447     phFUNCTION("phRWLock::readLock")
00448     int prc         = 0;
00449     int have_lock   = 0;
00450     int locked      = 0;
00451     int retrc       = phSUCCESS;
00452 #if defined(WIN32)
00453     DWORD dwResult  = 0;
00454     BOOL bResult    = TRUE;
00455 #endif    
00456     int first_reader= 0;
00457 
00458     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00459 
00460 #if RECURSIVE_SUPPORT()  
00461     /* check to see if this writer already has the lock */
00462     phMUTEX_LOCK(this->m_mutex,locked);
00463 
00464     DEBUG_PRINT("(this:%p)\twriter:%ld\n",
00465                  this,this->m_writer);
00466     if (this->m_writer != phRWLock_INVALIDOWNER)
00467     {
00468         DEBUG_PRINT("(this:%p)\tphTHREADS_EQUAL(self:%ld,writer:%ld))\n",
00469                      this,phGetCurrentThreadId(),this->m_writer);
00470         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
00471         {
00472             this->m_writer_nlocks++;
00473             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",
00474                      this,this->m_writer_nlocks);
00475             have_lock = 1;
00476             
00477             if (this->m_readers > 0)
00478             {
00479                 phERR_PRINT("There are readers but the writer has a lock.\n");
00480             }
00481         }
00482     }
00483    
00484     phMUTEX_UNLOCK(this->m_mutex,locked);
00485 #endif
00486 
00487     if (have_lock == 0)
00488     {
00489 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00490         /* int   pthread_rwlock_rdlock(pthread_rwlock_t *); */
00491         prc = rc = pthread_rwlock_rdlock(&(this->m_info->m_rwlock));
00492         rwlock_error(rc,"pthread_rwlock_rdlock");
00493         
00494         if (prc == EDEADLK) 
00495         { 
00496             /* XXX: rc = 0; */
00497             rc = phFAIL;
00498             phPRINT_RC(-1,"pthread_rwlock_rdlock","pthread_rwlock_rdlock: ERR DEAD LOCK");
00499         }
00500         /* else, if the return code isn't 0, then an error occured */
00501         else if (prc != 0)
00502         {
00503             rc = phFAIL;
00504         }
00505         phCHECK_RC(rc, "pthread_rwlock_rdlock", "read-locking this->m_info->m_rwlock failed");
00506 #endif
00507 #if defined(WIN32)
00508         /* If we're the first one to increment the counter, then we'll be
00509          * the reader responsible for letting the readers go */
00510         if (InterlockedIncrement(&this->m_info->m_reader_counter) == 0)
00511         { 
00512             /* Wait for the reader-writer mutex event */
00513             dwResult = WaitForSingleObject(this->m_info->m_rw_access_event, INFINITE);
00514             /* There was an error waiting on the thread */
00515             if (dwResult == WAIT_FAILED) 
00516             {
00517                 /* decrement the reader counter because we're no longer
00518                  * waiting */
00519                 InterlockedDecrement(&this->m_info->m_reader_counter);
00520                 rc      = phFAIL; 
00521                 retrc   = phFAIL;
00522             }
00523             else
00524             {
00525                 rc      = phSUCCESS;
00526                 retrc   = phSUCCESS;
00527             }
00528             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_reader_event.");    
00529                 
00530             /* I'm the first reader; needed for later on */
00531             first_reader = 1;
00532                 
00533             /* if we succeeded in getting the reader/writer mutex... */
00534             if (retrc == phSUCCESS)
00535             {
00536                 /* release all the waiting readers */
00537                 bResult = SetEvent(this->m_info->m_reader_event);
00538                 if (!bResult)
00539                 {
00540                     rc      = phFAIL;
00541                     retrc   = phFAIL;
00542                 }
00543                 else
00544                 {
00545                     rc      = phSUCCESS;
00546                     retrc   = phSUCCESS;
00547                 }
00548                 phPRINT_RC(rc,"SetEvent","SetEvent failed.");
00549             }
00550         }
00551            
00552         if ((retrc == phSUCCESS) && (first_reader == 0))
00553         {
00554             dwResult = WaitForSingleObject(this->m_info->m_reader_event,INFINITE);
00555             /* There was an error waiting on the thread */
00556             if (dwResult == WAIT_FAILED) 
00557             {
00558                 rc      = phFAIL; 
00559                 retrc   = phFAIL;
00560             }
00561             else
00562             {
00563                 rc      = phSUCCESS;
00564                 retrc   = phSUCCESS;
00565             }
00566             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_reader_event.");    
00567         }
00568 #endif
00569 
00570 #if defined(__ADSPBLACKFIN__)
00571         rc = this->m_info->m_reader_counter_mutex->lock();
00572         phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00573 
00574         if ((++this->m_info->m_reader_counter) == 0)
00575             first_reader = 1;
00576         
00577         rc = this->m_info->m_reader_counter_mutex->unlock();
00578         phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00579 
00580         /* if I'm the first reader, wait on the rw lock */
00581         if (first_reader == 1)
00582         {
00583             /* Lock the condition variable lock */
00584             rc = this->m_info->m_rw_access_event->lock();
00585             phCHECK_RC(rc,NULL,"m_rw_access_event->lock() failed");
00586 
00587             /* Wait for the condition to become true/1 */
00588             while (this->m_info->m_rw_access_event_value != 1)
00589             {
00590                 /* Wait to be woken up by another */
00591                 rc = this->m_info->m_rw_access_event->signalWait();
00592                 if (rc == phFAIL) /* failure : decrement reader count */
00593                 {
00594                     rc = this->m_info->m_reader_counter_mutex->lock();
00595                     phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00596 
00597                     this->m_info->m_reader_counter--;
00598         
00599                     rc = this->m_info->m_reader_counter_mutex->unlock();
00600                     phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00601 
00602                     rc    = phFAIL;
00603                     retrc = phFAIL;
00604                 }
00605                 phCHECK_RC(rc,NULL,"m_rw_access_event->signalWait() failed");
00606             }
00607 
00608             /* We don't need to signal/broadcast here because we're
00609              * not going to wake anyone up until the variable is true
00610              * again later when we unlock */
00611             this->m_info->m_rw_access_event_value = 0;
00612 
00613             /* Release the condition variable lock */
00614             rc = this->m_info->m_rw_access_event->unlock();
00615             phPRINT_RC(rc,NULL,"m_rw_access_event->unlock() failed");
00616 
00617             rc      = phSUCCESS;
00618             retrc   = phSUCCESS;
00619 
00620             /* if we succeeded, then let all the readers go through */
00621             if (retrc == phSUCCESS)
00622             {
00623                 /* Lock the condition variable lock */
00624                 rc = this->m_info->m_reader_event->lock();
00625                 phCHECK_RC(rc,NULL,"m_reader_event->lock() failed");
00626 
00627                 this->m_info->m_reader_event_value = 1;
00628 
00629                 /* release all the other readers */
00630                 rc = this->m_info->m_reader_event->broadcast();
00631                 phCHECK_RC(rc,NULL,"m_reader_event->broadcast() failed");
00632 
00633                 /* Release the condition variable lock */
00634                 rc = this->m_info->m_reader_event->unlock();
00635                 phCHECK_RC(rc,NULL,"m_reader_event->unlock() failed");
00636             }
00637         }
00638 
00639         /* if we're not the first reader then wait for the
00640          * event/condition that the first reader will set when we can
00641          * continue into the reader critical section */
00642         if ((retrc == phSUCCESS) && (first_reader == 0))
00643         {
00644             /* Lock the condition variable lock */
00645             rc = this->m_info->m_reader_event->lock();
00646             phCHECK_RC(rc,NULL,"m_reader_event->lock() failed");
00647 
00648             /* Wait for the condition to become true/1 */
00649             while (this->m_info->m_reader_event_value != 1)
00650             {
00651                 /* Wait to be woken up by another */
00652                 rc = this->m_info->m_reader_event->signalWait();
00653                 if (rc != phSUCCESS) /* failure : decrement reader count */
00654                 {
00655                     rc = this->m_info->m_reader_counter_mutex->lock();
00656                     phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00657 
00658                     this->m_info->m_reader_counter--;
00659         
00660                     rc = this->m_info->m_reader_counter_mutex->unlock();
00661                     phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00662 
00663                     rc      = phFAIL;
00664                     retrc   = phFAIL;
00665                 }
00666                 else
00667                 {
00668                     rc      = phSUCCESS;
00669                     retrc   = phSUCCESS;
00670                 }
00671                 phPRINT_RC(rc,NULL,"m_reader_event->signalWait() failed");
00672             }
00673 
00674             /* Release the condition variable lock */
00675             rc = this->m_info->m_reader_event->unlock();
00676             phPRINT_RC(rc,NULL,"m_reader_event->unlock() failed");
00677         }
00678 #endif
00679     }
00680 #if RECURSIVE_SUPPORT()  
00681     /* check to see if this writer already has the lock */
00682     phMUTEX_LOCK(this->m_mutex,locked);
00683 
00684     if (this->m_writer == phRWLock_INVALIDOWNER)
00685     {
00686         if (retrc == phSUCCESS)
00687         {
00688             this->m_readers++;
00689             DEBUG_PRINT("(this:%p)\treaders: %u\n",this,this->m_readers);
00690         }
00691     }
00692     else if (!have_lock)
00693     {
00694         phERR_PRINT("The reader succeeded but there is a writer with a lock.\n");
00695     }
00696     
00697     phMUTEX_UNLOCK(this->m_mutex,locked);
00698 #endif
00699 
00700     return retrc;
00701 error:
00702 #if RECURSIVE_SUPPORT()
00703     phMUTEX_ERROR_UNLOCK(this->m_mutex,locked);
00704 #endif
00705     return phFAIL;
00706 } 
00707 
00708 /* ---------------------------------------------------------------------- */
00709 int phRWLock::tryReadLock() 
00710 { 
00711     phFUNCTION("phRWLock::tryReadLock")
00712     int prc         = 0;
00713     int have_lock   = 0;
00714     int locked      = 0;
00715     int retrc       = phSUCCESS;
00716     int first_reader= 0;
00717 #if defined(WIN32)
00718     DWORD   dwResult    = 0;
00719     BOOL    bResult     = TRUE;
00720 #endif
00721     
00722     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00723     
00724 #if RECURSIVE_SUPPORT()  
00725     /* check to see if this writer already has the lock */
00726     phMUTEX_LOCK(this->m_mutex,locked);
00727 
00728     if (this->m_writer != phRWLock_INVALIDOWNER)
00729     {
00730         DEBUG_PRINT("(this:%p)\tphTHREADS_EQUAL(self:%ld,writer:%ld))\n",
00731                      this,phGetCurrentThreadId(),this->m_writer);
00732         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
00733         {
00734             this->m_writer_nlocks++;
00735             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",
00736                      this,this->m_writer_nlocks);
00737             have_lock = 1;
00738             
00739             if (this->m_readers > 0)
00740             {
00741                 phERR_PRINT("There are readers but the writer has a lock.\n");
00742             }
00743         }
00744     }
00745     
00746     phMUTEX_UNLOCK(this->m_mutex,locked);
00747 #endif
00748 
00749     /* int   pthread_rwlock_tryrdlock(pthread_rwlock_t *); */
00750     
00751     if (have_lock == 0)
00752     {
00753 #if defined(HAVE_PTHREAD) && !defined(WIN32)
00754         prc = rc = pthread_rwlock_tryrdlock(&(this->m_info->m_rwlock));
00755         if (prc != EBUSY) 
00756         {
00757             /* don't print on the busy err */
00758             rwlock_error(prc,"pthread_rwlock_tryrdlock");
00759         }
00760         if (prc == EDEADLK) 
00761         { 
00762             rc      = phFAIL; 
00763             retrc   = phRWLock_NOTLOCKED; 
00764             phPRINT_RC(-1,"pthread_rwlock_tryrdlock","pthread_rwlock_tryrdlock: ERR DEAD LOCK");
00765         }
00766         /* Non-blocking, return 1 to signify to calling function the locked
00767          * was not retrieved. don't return -1 because it'll print errors */
00768         else if (prc == EBUSY) 
00769         {
00770             rc      = phSUCCESS;
00771             retrc   = phRWLock_OWNED;
00772         }
00773         /* else, if the return code isn't 0, then an error occured */
00774         else if (prc != 0) 
00775         {
00776             rc = phFAIL;
00777         }
00778         phCHECK_RC(rc,"pthread_rwlock_tryrdlock","tryrdlock failed");
00779 #endif
00780 #if defined(WIN32)
00781         if (InterlockedIncrement(&this->m_info->m_reader_counter) == 0)
00782         { 
00783             dwResult = WaitForSingleObject(this->m_info->m_rw_access_event, 0L);
00784             /* There was an error waiting on the thread */
00785             if (dwResult == WAIT_FAILED) 
00786             {
00787                 InterlockedDecrement(&this->m_info->m_reader_counter);
00788                 rc      = phFAIL; 
00789                 retrc   = phFAIL;
00790             }
00791             else if (dwResult == WAIT_TIMEOUT)
00792             {
00793                 rc      = phSUCCESS;
00794                 retrc   = phRWLock_OWNED;
00795             }
00796             else
00797             {
00798                 rc      = phSUCCESS;
00799                 retrc   = phSUCCESS;
00800             }
00801             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_reader_event.");    
00802                 
00803             first_reader = 1;
00804                 
00805             if (retrc == phSUCCESS)
00806             {
00807                 bResult = SetEvent(this->m_info->m_reader_event);
00808                 if (!bResult)
00809                 {
00810                     rc      = phFAIL;
00811                     retrc   = phFAIL;
00812                 }
00813                 else
00814                 {
00815                     rc      = phSUCCESS;
00816                     retrc   = phSUCCESS;
00817                 }
00818                 phPRINT_RC(rc,"SetEvent","SetEvent failed.");
00819             }
00820         }
00821            
00822         if ((retrc == phSUCCESS) && (first_reader == 0))
00823         {
00824             dwResult = WaitForSingleObject(this->m_info->m_reader_event,0L);
00825             /* There was an error waiting on the thread */
00826             if (dwResult == WAIT_FAILED) 
00827             {
00828                 rc      = phFAIL; 
00829                 retrc   = phFAIL;
00830             }
00831             else if (WAIT_TIMEOUT)
00832             {
00833                 rc      = phSUCCESS;
00834                 retrc   = phRWLock_OWNED;
00835             }
00836             else
00837             {
00838                 rc      = phSUCCESS;
00839                 retrc   = phSUCCESS;
00840             }
00841             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_reader_event.");    
00842         }
00843 #endif
00844 #if defined(__ADSPBLACKFIN__)
00845         rc = this->m_info->m_reader_counter_mutex->lock();
00846         phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00847 
00848         if ((++this->m_info->m_reader_counter) == 0)
00849         {
00850             /* I'm the first reader if it's equal to 0 */
00851             first_reader = 1;
00852         }
00853         /* Release the lock on the reader counter */
00854         
00855         rc = this->m_info->m_reader_counter_mutex->unlock();
00856         phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00857 
00858         /* if I'm the first reader, wait on the rw lock */
00859         if (first_reader == 1)
00860         {
00861             /* Lock the condition variable lock */
00862             rc = this->m_info->m_rw_access_event->lock();
00863             phCHECK_RC(rc,NULL,"m_rw_access_event->lock() failed");
00864 
00865             /* Wait for the condition to become true/1 */
00866             if (this->m_info->m_rw_access_event_value != 1)
00867             {
00868                 rc = this->m_info->m_reader_counter_mutex->lock();
00869                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00870 
00871                 this->m_info->m_reader_counter--;
00872 
00873                 rc = this->m_info->m_reader_counter_mutex->unlock();
00874                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00875 
00876                 rc    = phFAIL;
00877                 retrc = phRWLock_OWNED;
00878             }
00879             else
00880             {
00881                 /* We don't need to signal/broadcast here because we're
00882                  * not going to wake anyone up until the variable is true
00883                  * again later when we unlock */
00884                 this->m_info->m_rw_access_event_value = 0;
00885 
00886                 rc      = phSUCCESS;
00887                 retrc   = phSUCCESS;
00888             }
00889                 
00890             /* Release the condition variable lock */
00891             rc = this->m_info->m_rw_access_event->unlock();
00892             phPRINT_RC(rc,NULL,"m_rw_access_event->unlock() failed");
00893 
00894             /* if we succeeded, then let all the readers go through */
00895             if (retrc == phSUCCESS)
00896             {
00897                 /* Lock the condition variable lock */
00898                 rc = this->m_info->m_reader_event->lock();
00899                 phCHECK_RC(rc,NULL,"m_reader_event->lock() failed");
00900 
00901                 this->m_info->m_reader_event_value = 1;
00902                     
00903                 /* release all the other readers */
00904                 rc = this->m_info->m_reader_event->broadcast();
00905                 phCHECK_RC(rc,NULL,"m_reader_event->broadcast() failed");
00906 
00907                 /* Release the condition variable lock */
00908                 rc = this->m_info->m_reader_event->unlock();
00909                 phCHECK_RC(rc,NULL,"m_reader_event->unlock() failed");
00910             }
00911         }
00912 
00913         /* if we're not the first reader then wait for the
00914          * event/condition that the first reader will set when we can
00915          * continue into the reader critical section */
00916         if ((retrc == phSUCCESS) && (first_reader == 0))
00917         {
00918             /* Lock the condition variable lock */
00919             rc = this->m_info->m_reader_event->lock();
00920             phCHECK_RC(rc,NULL,"m_reader_event->lock() failed");
00921 
00922             /* Wait for the condition to become true/1 */
00923             if (this->m_info->m_reader_event_value == 0)
00924             {
00925                 rc = this->m_info->m_reader_counter_mutex->lock();
00926                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
00927 
00928                 this->m_info->m_reader_counter--;
00929         
00930                 rc = this->m_info->m_reader_counter_mutex->unlock();
00931                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
00932 
00933                 rc    = phSUCCESS;
00934                 retrc = phRWLock_OWNED;
00935             }
00936             else
00937             {
00938                 rc = phSUCCESS;
00939                 retrc = phSUCCESS;
00940             }
00941             
00942             /* Release the condition variable lock */
00943             rc = this->m_info->m_reader_event->unlock();
00944             phPRINT_RC(rc,NULL,"m_reader_event->unlock() failed");
00945         }
00946 #endif
00947     }
00948 #if RECURSIVE_SUPPORT()  
00949     /* check to see if this writer already has the lock */
00950     phMUTEX_LOCK(this->m_mutex,locked);
00951 
00952     if (this->m_writer == phRWLock_INVALIDOWNER)
00953     {
00954         if (retrc == phSUCCESS)
00955         {
00956             this->m_readers++;
00957             DEBUG_PRINT("readers: %u\n",this->m_readers);
00958         }
00959     }
00960     else if (!have_lock)
00961     {
00962         phERR_PRINT("The reader succeeded but there is a writer with a lock.\n");
00963     }
00964 
00965     phMUTEX_UNLOCK(this->m_mutex,locked);
00966 #endif
00967 
00968 
00969     return retrc;
00970 
00971 error:
00972 #if RECURSIVE_SUPPORT()
00973     phMUTEX_ERROR_UNLOCK(this->m_mutex,locked);
00974 #endif
00975     
00976     return phFAIL;
00977 }
00978 
00979 /* ---------------------------------------------------------------------- */
00980 int phRWLock::writeLock() 
00981 { 
00982     phFUNCTION("phRWLock::writeLock")
00983     int prc         = 0;
00984     int have_lock   = 0;
00985     int locked      = 0;
00986     int retrc       = phSUCCESS;
00987 #if defined(WIN32)
00988     DWORD dwResult  = 0;
00989     BOOL bResult    = TRUE;
00990 #endif
00991 
00992     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
00993 
00994     /* int   pthread_rwlock_wrlock(pthread_rwlock_t *); */
00995 #if RECURSIVE_SUPPORT()  
00996     /* check to see if this writer already has the lock */
00997     phMUTEX_LOCK(this->m_mutex,locked);
00998 
00999     if (this->m_writer != phRWLock_INVALIDOWNER)
01000     {
01001         DEBUG_PRINT("(this:%p)\tphTHREADS_EQUAL(self:%ld,writer:%ld))\n",
01002                      this,phGetCurrentThreadId(),this->m_writer);
01003         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
01004         {
01005             this->m_writer_nlocks++;
01006             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",
01007                      this,this->m_writer_nlocks);
01008             have_lock = 1;
01009             
01010             if (this->m_readers > 0)
01011             {
01012                 phERR_PRINT("There are readers but the writer has a lock.\n");
01013             }
01014         }
01015     }
01016     
01017     phMUTEX_UNLOCK(this->m_mutex,locked);
01018 #endif
01019     /* only allow one lock call per writer */
01020     if (have_lock == 0)
01021     {
01022 #if defined(HAVE_PTHREAD) && !defined(WIN32)
01023         prc = rc = pthread_rwlock_wrlock(&(this->m_info->m_rwlock));
01024         rwlock_error(rc,"pthread_rwlock_wrlock");
01025         if (prc == EDEADLK) 
01026         { 
01027             /* XXX: rc = 0; */
01028             retrc = phFAIL; 
01029             phPRINT_RC(-1,"pthread_rwlock_wrlock",
01030                      "pthread_rwlock_wrdlock: ERR DEAD LOCK");
01031         }
01032         /* else, if the return code isn't 0, then an error occured */
01033         else if (prc != 0) 
01034         {
01035             retrc = phFAIL;
01036             phPRINT_RC(rc, "pthread_rwlock_wrlock", "write-locking this->m_info->m_rwlock failed");
01037         }
01038 #endif /* WIN32 */
01039 #if defined(WIN32)
01040         /* We can only have one writer at a time. Get the exclusive access
01041          * to the writer critical section */
01042         dwResult = WaitForSingleObject(this->m_info->m_writer_mutex,INFINITE);
01043         /* There was an error waiting on the thread */
01044         if (dwResult == WAIT_FAILED) 
01045         {
01046             rc      = phFAIL; 
01047             retrc   = phFAIL;
01048         }
01049         else
01050         {
01051             rc      = phSUCCESS;
01052             retrc   = phSUCCESS;
01053         }
01054         phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_writer_mutex.");    
01055     
01056         if (retrc == phSUCCESS)
01057         {
01058             /* Wait for to get access to the real lock */
01059             /* Either readers are running or a writer is running, this
01060              * event here determines who is running */
01061             dwResult = WaitForSingleObject(this->m_info->m_rw_access_event, INFINITE);
01062             if (dwResult == WAIT_FAILED) 
01063             {
01064                 rc      = phFAIL; 
01065                 retrc   = phFAIL;
01066 
01067                 bResult = ReleaseMutex(this->m_info->m_writer_mutex);
01068                 if (!bResult)
01069                 {
01070                     phPRINT_RC(phFAIL,"ReleaseMutex","ReleaseMutex failed.");
01071                 }
01072             }
01073             else
01074             {
01075                 rc      = phSUCCESS;
01076                 retrc   = phSUCCESS;
01077             }
01078             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_rw_access_event.");    
01079         }
01080 #endif
01081 
01082 #if defined(__ADSPBLACKFIN__)
01083         rc = this->m_info->m_writer_mutex->lock();
01084         phCHECK_RC(rc,NULL,"this->m_info->m_writer_mutex->lock()");
01085         
01086         /* Lock the condition variable lock */
01087         rc = this->m_info->m_rw_access_event->lock();
01088         phCHECK_RC(rc,NULL,"m_rw_access_event->lock() failed");
01089 
01090         /* Wait for the condition to become true/1 */
01091         while (this->m_info->m_rw_access_event_value != 1)
01092         {
01093             /* Wait to be woken up by another */
01094             rc = this->m_info->m_rw_access_event->signalWait();
01095             if (rc != phSUCCESS) /* failure : decrement reader count */
01096             {
01097                 rc    = phFAIL;
01098                 retrc = phFAIL;
01099         
01100                 rc = this->m_info->m_writer_mutex->unlock();
01101                 phPRINT_RC(rc,NULL,"this->m_info->m_writer_mutex->unlock()");
01102             }
01103             phCHECK_RC(rc,NULL,"m_rw_access_event->signalWait() failed");
01104         }
01105 
01106         /* We don't need to signal/broadcast here because we're
01107          * not going to wake anyone up until the variable is true
01108          * again later when we unlock */
01109         this->m_info->m_rw_access_event_value = 0;
01110 
01111         /* Release the condition variable lock */
01112         rc = this->m_info->m_rw_access_event->unlock();
01113         phPRINT_RC(rc,NULL,"m_rw_access_event->unlock() failed");
01114 #endif
01115 
01116 #if RECURSIVE_SUPPORT()  
01117         if (retrc == phSUCCESS)
01118         {
01119             phMUTEX_LOCK(this->m_mutex,locked);
01120             
01121             this->m_writer = phGetCurrentThreadId();
01122             this->m_writer_nlocks++;
01123             
01124             if (this->m_readers > 0)
01125             {
01126                 phERR_PRINT("There are readers but the writer has a lock.\n");
01127             }
01128 
01129             DEBUG_PRINT("(this:%p)\twriter:%ld\n",
01130                         this,this->m_writer);
01131             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",
01132                         this,this->m_writer_nlocks);
01133             
01134             phMUTEX_UNLOCK(this->m_mutex,locked);
01135         }
01136 #endif
01137     }
01138     
01139     return retrc;
01140 error:
01141 #if RECURSIVE_SUPPORT()
01142     phMUTEX_ERROR_UNLOCK(this->m_mutex,locked);
01143 #endif
01144     
01145     return phFAIL;
01146 } 
01147 
01148 /* ---------------------------------------------------------------------- */
01149 int phRWLock::tryWriteLock() 
01150 { 
01151     phFUNCTION("phRWLock::tryWriteLock")
01152     int prc         = 0;
01153     int have_lock   = 0;
01154     int retrc       = phSUCCESS;
01155     int locked      = 0;
01156 #if defined(WIN32)
01157     DWORD dwResult  = 0;
01158     BOOL bResult    = TRUE;
01159 #endif
01160     
01161     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
01162     
01163 #if RECURSIVE_SUPPORT()  
01164     /* check to see if this writer already has the lock */
01165     phMUTEX_LOCK(this->m_mutex,locked);
01166 
01167     if (this->m_writer != phRWLock_INVALIDOWNER)
01168     {
01169         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
01170         {
01171             this->m_writer_nlocks++;
01172             have_lock = 1;
01173             
01174             if (this->m_readers > 0)
01175             {
01176                 phERR_PRINT("There are readers but the writer has a lock.\n");
01177             }
01178 
01179             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",this,this->m_writer_nlocks);
01180         }
01181     }
01182 #endif    
01183     /* int   pthread_rwlock_trywrlock(pthread_rwlock_t *); */
01184 
01185     /* if this thread doesn't own the lock already */
01186     if (have_lock == 0)
01187     {
01188 #if defined(HAVE_PTHREAD) && !defined(WIN32)
01189         prc = rc = pthread_rwlock_trywrlock(&(this->m_info->m_rwlock));
01190         if (prc != EBUSY)
01191         { 
01192             /* don't print on the busy err */
01193             rwlock_error(prc,"pthread_rwlock_trywrlock");
01194         }
01195         
01196         if (prc == EDEADLK) 
01197         {
01198             /* XXX: rc = 0; */
01199             rc      = phFAIL; 
01200             retrc   = phRWLock_NOTLOCKED; 
01201             phPRINT_RC(-1,"pthread_rwlock_trywrlock","pthread_rwlock_trywrlock: ERR DEAD LOCK");
01202         }
01203         else if (prc == EBUSY)
01204         {
01205             rc      = phSUCCESS;
01206             retrc   = phRWLock_OWNED;
01207         }
01208         /* else, if the return code isn't 0, then an error occured */
01209         else if (prc != 0) 
01210         {
01211             rc      = phFAIL;
01212             retrc   = phFAIL;
01213         }
01214         phCHECK_RC(rc,"pthread_rwlock_trywrlock","trywrlock failed");
01215 #endif
01216 
01217 #if defined(WIN32)
01218         dwResult = WaitForSingleObject(this->m_info->m_writer_mutex,0L);
01219         /* There was an error waiting on the thread */
01220         if (dwResult == WAIT_FAILED) 
01221         {
01222             rc      = phFAIL; 
01223             retrc   = phFAIL;
01224         }
01225         else if (dwResult == WAIT_TIMEOUT)
01226         {
01227             rc      = phSUCCESS;
01228             retrc   = phRWLock_OWNED;
01229         }
01230         else
01231         {
01232             rc      = phSUCCESS;
01233             retrc   = phSUCCESS;
01234         }
01235         phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_writer_mutex.");    
01236     
01237         if (retrc == phSUCCESS)
01238         {
01239             /* Wait for to get access to the real lock */
01240             /* Either readers are running or a writer is running, this
01241              * event here determines who is running */
01242             dwResult = WaitForSingleObject(this->m_info->m_rw_access_event, 0L);
01243             if (dwResult == WAIT_FAILED) 
01244             {
01245                 rc      = phFAIL; 
01246                 retrc   = phFAIL;
01247             }
01248             else if (dwResult == WAIT_TIMEOUT)
01249             {
01250                 rc      = phSUCCESS;
01251                 retrc   = phRWLock_OWNED;
01252             }
01253             else
01254             {
01255                 rc      = phSUCCESS;
01256                 retrc   = phSUCCESS;
01257             }
01258             phPRINT_RC(rc,"WaitForSingleObject","Wait on failed: this->m_info->m_rw_access_event.");    
01259 
01260             /* Release the write_event, we failed to get the rw_access_event */
01261             if (retrc != phSUCCESS)
01262             {
01263                 bResult = ReleaseMutex(this->m_info->m_writer_mutex);
01264                 if (!bResult)
01265                 {
01266                     rc = phFAIL;
01267                 }
01268                 else
01269                 {
01270                     rc = phSUCCESS;
01271                 }
01272                 phPRINT_RC(rc,"ReleaseMutex","ReleaseMutex failed.");
01273             }
01274         }
01275 #endif
01276 
01277 #if defined(__ADSPBLACKFIN__)
01278         rc = this->m_info->m_writer_mutex->trylock();
01279         phCHECK_RC(rc,NULL,"this->m_info->m_writer_mutex->trylock()");
01280 
01281         if (rc == phSUCCESS)
01282         {
01283             /* Lock the condition variable lock */
01284             rc = this->m_info->m_rw_access_event->lock();
01285             phCHECK_RC(rc,NULL,"m_rw_access_event->lock() failed");
01286 
01287             /* Wait for the condition to become true/1 */
01288             if (this->m_info->m_rw_access_event_value != 1)
01289             {
01290                 rc      = phSUCCESS;
01291                 retrc   = phRWLock_OWNED;
01292         
01293                 rc = this->m_info->m_writer_mutex->unlock();
01294                 phCHECK_RC(rc,NULL,"this->m_info->m_writer_mutex->unlock()");
01295             }
01296             else
01297             {
01298                 rc      = phSUCCESS;
01299                 retrc   = phSUCCESS;
01300 
01301                 /* We don't need to signal/broadcast here because we're
01302                  * not going to wake anyone up until the variable is true
01303                  * again later when we unlock */
01304                 this->m_info->m_rw_access_event_value = 0;
01305             }
01306 
01307             /* Release the condition variable lock */
01308             rc = this->m_info->m_rw_access_event->unlock();
01309             phPRINT_RC(rc,NULL,"m_rw_access_event->unlock() failed");
01310         }
01311 #endif
01312 
01313 #if RECURSIVE_SUPPORT()  
01314         /* if this thread got the write lock */
01315         if (retrc == phSUCCESS)
01316         {
01317             this->m_writer = phGetCurrentThreadId();
01318             this->m_writer_nlocks++;
01319             DEBUG_PRINT("(this:%p)\twriter:%ld\n",
01320                         this,this->m_writer);
01321             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",
01322                         this,this->m_writer_nlocks);
01323 
01324             if (this->m_readers > 0)
01325             {
01326                 phERR_PRINT("There are readers but the writer has a lock.\n");
01327             }
01328         }
01329 #endif
01330     }
01331     
01332 #if RECURSIVE_SUPPORT()  
01333     phMUTEX_UNLOCK(this->m_mutex,locked);
01334 #endif
01335 
01336     return retrc;
01337 error:
01338 #if RECURSIVE_SUPPORT()  
01339     phMUTEX_ERROR_UNLOCK(this->m_mutex,locked);
01340 #endif
01341 
01342     return phFAIL;
01343 } 
01344 
01345 /* ---------------------------------------------------------------------- */
01346 int phRWLock::rwUnlock() 
01347 { 
01348     phFUNCTION("phRWLock::rwUnlock")
01349     int prc         = 0;
01350     int can_unlock  = 1;
01351     int locked      = 0;
01352     int retrc       = phSUCCESS;
01353 #if defined(WIN32)
01354     BOOL bResult = TRUE;
01355 #endif
01356 
01357     DEBUG_PRINT("(this:%p)thread:%ld\n",this,phGetCurrentThreadId());
01358 
01359 #if RECURSIVE_SUPPORT()  
01360     /* check to see if this is a writer lock.
01361      * it's a writer lock if the writer thread var is set */
01362     phMUTEX_LOCK(this->m_mutex,locked);
01363     /*
01364     rc = this->m_mutex.lock();
01365     phPRINT_RC(rc,NULL,"m_mutex.lock()");
01366     if (rc == 0) locked = 1;
01367     else goto rwunlock;
01368     */
01369 
01370     if (this->m_writer != phRWLock_INVALIDOWNER)
01371     {
01372         /* if this isn't the owning thread, then return an 
01373          * error */
01374         DEBUG_PRINT("(this:%p)\tphTHREADS_EQUAL(self:%ld,writer:%ld))\n",
01375                      this,phGetCurrentThreadId(),this->m_writer);
01376         if (phTHREADS_EQUAL(phGetCurrentThreadId(),this->m_writer))
01377         {
01378             this->m_writer_nlocks--;
01379             DEBUG_PRINT("(this:%p)\tnlocks:%u\n",this,this->m_writer_nlocks);
01380             
01381             if (this->m_writer_nlocks > 0)
01382             {
01383                 DEBUG_PRINT("(this:%p)\tcan_unlock = 0;\n",this);
01384                 can_unlock = 0;
01385             }
01386             else
01387             {
01388                 DEBUG_PRINT("(this:%p)\tthis->m_writer = 0x0;\n",this);
01389                 this->m_writer = phRWLock_INVALIDOWNER;
01390                 can_unlock = 2;
01391             }
01392         }
01393         else
01394         {
01395             phCHECK_RC(-1,NULL,"This is a writer's lock and this thread doesn't own it.");
01396         }
01397     }
01398     else
01399     {
01400         this->m_readers--;
01401         DEBUG_PRINT("readers: %u\n",this->m_readers);
01402     }
01403 #endif
01404     
01405 /*rwunlock:*/
01406 
01407     /* If we're allowed to unlock the lock, do it... do it */
01408     if (can_unlock > 0)
01409     {
01410 #if defined(HAVE_PTHREAD) && !defined(WIN32)
01411         /* int   pthread_rwlock_unlock(pthread_rwlock_t *); */
01412         prc = rc = pthread_rwlock_unlock(&(this->m_info->m_rwlock));
01413         if (prc != 0)
01414         {
01415             rc = phFAIL;
01416         }
01417         can_unlock = 0;
01418         phCHECK_RC(rc, "pthread__unlock", "unlocking this->m_info->m_rwlock failed");
01419         if (prc != EBUSY) rwlock_error(rc,"pthread_rwlock_unlock");
01420 #endif
01421 #if defined(WIN32) || defined(__ADSPBLACKFIN__)
01422         /* We're a writer */
01423         if (can_unlock == 2)
01424         {
01425         #if defined(WIN32)
01426             bResult = SetEvent(this->m_info->m_rw_access_event);
01427             if (!bResult)
01428             {
01429                 rc      = phFAIL;
01430                 retrc   = phFAIL;
01431             }
01432             else
01433             {
01434                 rc      = phSUCCESS;
01435                 retrc   = phSUCCESS;
01436             }
01437             phPRINT_RC(rc,"SetEvent","SetEvent failed.");
01438             
01439             bResult = ReleaseMutex(this->m_info->m_writer_mutex);
01440             if (!bResult)
01441             {
01442                 rc      = phFAIL;
01443                 retrc   = phFAIL;
01444             }
01445             else
01446             {
01447                 rc      = phSUCCESS;
01448                 retrc   = phSUCCESS;
01449             }
01450             phPRINT_RC(rc,"ReleaseMutex","ReleaseMutex failed.");
01451         #endif
01452         #if defined(__ADSPBLACKFIN__)
01453             /* Reset the reader/writer access event */
01454             rc = this->m_info->m_rw_access_event->lock();
01455             phPRINT_RC(rc,NULL,"m_reader_event_access_event->lock() failed.");
01456 
01457             this->m_info->m_rw_access_event_value = 1;
01458 
01459             rc = this->m_info->m_rw_access_event->broadcast();
01460             phPRINT_RC(rc,NULL,"this->m_info->m_rw_access_event->broadcast failed.");
01461            
01462             rc = this->m_info->m_rw_access_event->unlock();
01463             phPRINT_RC(rc,NULL,"m_reader_event_access_event->unlock() failed.");
01464 
01465             /* release the writer mutex */
01466             rc = this->m_info->m_writer_mutex->unlock();
01467             phCHECK_RC(rc,NULL,"this->m_info->m_writer_mutex->unlock()");
01468         #endif
01469         }
01470         /* We're a reader */
01471         else
01472         {
01473         #if defined(WIN32)
01474             if (InterlockedDecrement(&this->m_info->m_reader_counter) < 0)
01475             { 
01476                 bResult = ResetEvent(this->m_info->m_reader_event);
01477                 if (!bResult)
01478                 {
01479                     rc      = phFAIL;
01480                     retrc   = phFAIL;
01481                 }
01482                 else
01483                 {
01484                     rc      = phSUCCESS;
01485                     retrc   = phSUCCESS;
01486                 }
01487                 phPRINT_RC(rc,"ResetEvent","ResetEvent failed.");
01488                 
01489                 /* Let either a set of readers go or a writer */
01490                 /* Whether or not anyone is waiting, the next
01491                  * reader/writer through will get access */
01492                 bResult = SetEvent(this->m_info->m_rw_access_event);
01493                 if (!bResult)
01494                 {
01495                     rc      = phFAIL;
01496                     retrc   = phFAIL;
01497                 }
01498                 else
01499                 {
01500                     rc      = phSUCCESS;
01501                     retrc   = phSUCCESS;
01502                 }
01503                 phPRINT_RC(rc,"SetEvent","SetEvent failed.");
01504             }
01505         #endif
01506         #if defined(__ADSPBLACKFIN__)
01507             int last_reader = 0;
01508 
01509             rc = this->m_info->m_reader_counter_mutex->lock();
01510             phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->lock()");
01511 
01512             if ((--this->m_info->m_reader_counter) < 0)
01513             {
01514                 /* I'm the first reader if it's equal to 0 */
01515                 last_reader = 1;
01516             }
01517             else
01518             {   
01519                 rc = this->m_info->m_reader_counter_mutex->unlock();
01520                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
01521             }
01522             
01523             if (last_reader)
01524             { 
01525                 /* reset the reader-session event */
01526                 rc = this->m_info->m_reader_event->lock();
01527                 phPRINT_RC(rc,NULL,"m_reader_event->lock() failed.");
01528 
01529                 this->m_info->m_reader_event_value = 0;
01530 
01531                 rc = this->m_info->m_reader_event->unlock();
01532                 phPRINT_RC(rc,NULL,"m_reader_event->unlock() failed.");
01533                 
01534                 rc = this->m_info->m_reader_counter_mutex->unlock();
01535                 phCHECK_RC(rc,NULL,"this->m_info->m_reader_counter_mutex->unlock()");
01536                 /* Reset the reader/writer access event */
01537                 
01538                 rc = this->m_info->m_rw_access_event->lock();
01539                 phPRINT_RC(rc,NULL,"m_reader_event_access_event->lock() failed.");
01540 
01541                 this->m_info->m_rw_access_event_value = 1;
01542 
01543                 rc = this->m_info->m_rw_access_event->broadcast();
01544                 phPRINT_RC(rc,NULL,"this->m_info->m_rw_access_event->broadcast failed.");
01545                 
01546                 rc = this->m_info->m_rw_access_event->unlock();
01547                 phPRINT_RC(rc,NULL,"m_reader_event_access_event->unlock() failed.");
01548             }
01549         #endif
01550         }
01551 #endif
01552     }
01553     
01554 #if RECURSIVE_SUPPORT()  
01555     phMUTEX_UNLOCK(this->m_mutex,locked);
01556 #endif
01557 
01558     return retrc;
01559 error:
01560 #if RECURSIVE_SUPPORT()  
01561     phMUTEX_ERROR_UNLOCK(this->m_mutex,locked);
01562 #endif
01563 
01564     return phFAIL;
01565 } 
01566 
01567 




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