change log updated
[public/netxms.git] / include / rwlock.h
index 8eb628e..da51695 100644 (file)
@@ -1,11 +1,11 @@
 /* 
 ** NetXMS - Network Management System
 ** NetXMS Foundation Library
-** Copyright (C) 2003, 2004, 2005, 2006 Victor Kirhenshtein
+** Copyright (C) 2003-2010 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
+** it under the terms of the GNU Lesser General Public License as published
+** by the Free Software Foundation; either version 3 of the License, or
 ** (at your option) any later version.
 **
 ** This program is distributed in the hope that it will be useful,
@@ -13,7 +13,7 @@
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 **
-** You should have received a copy of the GNU General Public License
+** You should have received a copy of the GNU Lesser General Public License
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
@@ -50,7 +50,7 @@ inline void RWLockDestroy(RWLOCK hLock)
    }
 }
 
-inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
+inline BOOL RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut)
 {
        BOOL ret = FALSE;
 
@@ -77,7 +77,7 @@ inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
                        timeout.tv_sec += now.tv_usec / 1000000;
                        timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
 
-                       retcode = pthread_rwlock_timedrdlock(hLock, &timeout);
+                       ret = (pthread_rwlock_timedrdlock(hLock, &timeout) == 0);
 #else
                        for(int i = (dwTimeOut / 50) + 1; i > 0; i--) 
          {
@@ -94,7 +94,7 @@ inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
    return ret;
 }
 
-inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
+inline BOOL RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut)
 {
        BOOL ret = FALSE;
 
@@ -121,7 +121,7 @@ inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
                        timeout.tv_sec += now.tv_usec / 1000000;
                        timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
 
-                       retcode = pthread_rwlock_timedwrlock(hLock, &timeout);
+                       ret = (pthread_rwlock_timedwrlock(hLock, &timeout) == 0);
 #else
                        for(int i = (dwTimeOut / 50) + 1; i > 0; i--) 
          {
@@ -144,7 +144,94 @@ inline void RWLockUnlock(RWLOCK hLock)
       pthread_rwlock_unlock(hLock);
 }
 
-#else    /* HAVE_PTHREAD_RWLOCK */
+#elif defined(_USE_GNU_PTH)
+
+typedef pth_rwlock_t * RWLOCK;
+
+inline RWLOCK RWLockCreate(void)
+{
+   RWLOCK hLock;
+
+   hLock = (RWLOCK)malloc(sizeof(pth_rwlock_t));
+   if (!pth_rwlock_init(hLock))
+   {
+      free(hLock);
+      hLock = NULL;
+   }
+   return hLock;
+}
+
+inline void RWLockDestroy(RWLOCK hLock)
+{
+   if (hLock != NULL)
+   {
+      free(hLock);
+   }
+}
+
+inline BOOL RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut)
+{
+       BOOL ret = FALSE;
+
+   if (hLock != NULL) 
+   {
+               if (dwTimeOut == INFINITE)
+               {
+                       if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RD, FALSE, NULL)) 
+         {
+                               ret = TRUE;
+                       }
+               }
+               else
+               {
+         pth_event_t ev;
+
+         ev = pth_event(PTH_EVENT_TIME, pth_timeout(dwTimeOut / 1000, (dwTimeOut % 1000) * 1000));
+                       if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RD, FALSE, ev)) 
+         {
+                               ret = TRUE;
+                       }
+         pth_event_free(ev, PTH_FREE_ALL);
+               }
+       }
+   return ret;
+}
+
+inline BOOL RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut)
+{
+       BOOL ret = FALSE;
+
+   if (hLock != NULL) 
+   {
+               if (dwTimeOut == INFINITE)
+               {
+                       if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RW, FALSE, NULL)) 
+         {
+                               ret = TRUE;
+                       }
+               }
+               else
+               {
+         pth_event_t ev;
+
+         ev = pth_event(PTH_EVENT_TIME, pth_timeout(dwTimeOut / 1000, (dwTimeOut % 1000) * 1000));
+                       if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RW, FALSE, ev)) 
+         {
+                               ret = TRUE;
+                       }
+         pth_event_free(ev, PTH_FREE_ALL);
+               }
+       }
+   return ret;
+}
+
+inline void RWLockUnlock(RWLOCK hLock)
+{
+   if (hLock != NULL)
+      pth_rwlock_release(hLock);
+}
+
+#else    /* not HAVE_PTHREAD_RWLOCK and not defined _USE_GNU_PTH */
 
 struct __rwlock_data
 {
@@ -157,19 +244,25 @@ struct __rwlock_data
    pthread_cond_t m_condRead;
    pthread_cond_t m_condWrite;
 #endif
-   DWORD m_dwWaitReaders;
-   DWORD m_dwWaitWriters;
+   UINT32 m_dwWaitReaders;
+   UINT32 m_dwWaitWriters;
    int m_iRefCount;  // -1 for write lock, otherwise number of read locks
 };
 
 typedef struct __rwlock_data * RWLOCK;
 
-RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate(void);
+RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate();
 void LIBNETXMS_EXPORTABLE RWLockDestroy(RWLOCK hLock);
-BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut);
-BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut);
+BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut);
+BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut);
 void LIBNETXMS_EXPORTABLE RWLockUnlock(RWLOCK hLock);
 
 #endif
 
+inline void RWLockPreemptiveWriteLock(RWLOCK hLock, UINT32 dwTimeout, UINT32 dwSleep)
+{
+       while(!RWLockWriteLock(hLock, dwTimeout))
+               ThreadSleepMs(dwSleep);
+}
+
 #endif