2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003, 2004, 2005, 2006 Victor Kirhenshtein
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #if HAVE_PTHREAD_RWLOCK
29 typedef pthread_rwlock_t
* RWLOCK
;
31 inline RWLOCK
RWLockCreate(void)
35 hLock
= (RWLOCK
)malloc(sizeof(pthread_rwlock_t
));
36 if (pthread_rwlock_init(hLock
, NULL
) != 0)
44 inline void RWLockDestroy(RWLOCK hLock
)
48 pthread_rwlock_destroy(hLock
);
53 inline BOOL
RWLockReadLock(RWLOCK hLock
, DWORD dwTimeOut
)
59 if (dwTimeOut
== INFINITE
)
61 if (pthread_rwlock_rdlock(hLock
) == 0)
68 #if HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
70 struct timespec timeout
;
72 // FIXME: there should be more accurate way
73 gettimeofday(&now
, NULL
);
74 timeout
.tv_sec
= now
.tv_sec
+ (dwTimeOut
/ 1000);
76 now
.tv_usec
+= (dwTimeOut
% 1000) * 1000;
77 timeout
.tv_sec
+= now
.tv_usec
/ 1000000;
78 timeout
.tv_nsec
= (now
.tv_usec
% 1000000) * 1000;
80 ret
= (pthread_rwlock_timedrdlock(hLock
, &timeout
) == 0);
82 for(int i
= (dwTimeOut
/ 50) + 1; i
> 0; i
--)
84 if (pthread_rwlock_tryrdlock(hLock
) == 0)
97 inline BOOL
RWLockWriteLock(RWLOCK hLock
, DWORD dwTimeOut
)
103 if (dwTimeOut
== INFINITE
)
105 if (pthread_rwlock_wrlock(hLock
) == 0)
112 #if HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
114 struct timespec timeout
;
116 // FIXME: there should be more accurate way
117 gettimeofday(&now
, NULL
);
118 timeout
.tv_sec
= now
.tv_sec
+ (dwTimeOut
/ 1000);
120 now
.tv_usec
+= (dwTimeOut
% 1000) * 1000;
121 timeout
.tv_sec
+= now
.tv_usec
/ 1000000;
122 timeout
.tv_nsec
= (now
.tv_usec
% 1000000) * 1000;
124 ret
= (pthread_rwlock_timedwrlock(hLock
, &timeout
) == 0);
126 for(int i
= (dwTimeOut
/ 50) + 1; i
> 0; i
--)
128 if (pthread_rwlock_trywrlock(hLock
) == 0)
141 inline void RWLockUnlock(RWLOCK hLock
)
144 pthread_rwlock_unlock(hLock
);
147 #elif defined(_USE_GNU_PTH)
149 typedef pth_rwlock_t
* RWLOCK
;
151 inline RWLOCK
RWLockCreate(void)
155 hLock
= (RWLOCK
)malloc(sizeof(pth_rwlock_t
));
156 if (!pth_rwlock_init(hLock
))
164 inline void RWLockDestroy(RWLOCK hLock
)
172 inline BOOL
RWLockReadLock(RWLOCK hLock
, DWORD dwTimeOut
)
178 if (dwTimeOut
== INFINITE
)
180 if (pth_rwlock_acquire(hLock
, PTH_RWLOCK_RD
, FALSE
, NULL
))
189 ev
= pth_event(PTH_EVENT_TIME
, pth_timeout(dwTimeOut
/ 1000, (dwTimeOut
% 1000) * 1000));
190 if (pth_rwlock_acquire(hLock
, PTH_RWLOCK_RD
, FALSE
, ev
))
194 pth_event_free(ev
, PTH_FREE_ALL
);
200 inline BOOL
RWLockWriteLock(RWLOCK hLock
, DWORD dwTimeOut
)
206 if (dwTimeOut
== INFINITE
)
208 if (pth_rwlock_acquire(hLock
, PTH_RWLOCK_RW
, FALSE
, NULL
))
217 ev
= pth_event(PTH_EVENT_TIME
, pth_timeout(dwTimeOut
/ 1000, (dwTimeOut
% 1000) * 1000));
218 if (pth_rwlock_acquire(hLock
, PTH_RWLOCK_RW
, FALSE
, ev
))
222 pth_event_free(ev
, PTH_FREE_ALL
);
228 inline void RWLockUnlock(RWLOCK hLock
)
231 pth_rwlock_release(hLock
);
234 #else /* not HAVE_PTHREAD_RWLOCK and not defined _USE_GNU_PTH */
243 pthread_mutex_t m_mutex
;
244 pthread_cond_t m_condRead
;
245 pthread_cond_t m_condWrite
;
247 DWORD m_dwWaitReaders
;
248 DWORD m_dwWaitWriters
;
249 int m_iRefCount
; // -1 for write lock, otherwise number of read locks
252 typedef struct __rwlock_data
* RWLOCK
;
254 RWLOCK LIBNETXMS_EXPORTABLE
RWLockCreate();
255 void LIBNETXMS_EXPORTABLE
RWLockDestroy(RWLOCK hLock
);
256 BOOL LIBNETXMS_EXPORTABLE
RWLockReadLock(RWLOCK hLock
, DWORD dwTimeOut
);
257 BOOL LIBNETXMS_EXPORTABLE
RWLockWriteLock(RWLOCK hLock
, DWORD dwTimeOut
);
258 void LIBNETXMS_EXPORTABLE
RWLockUnlock(RWLOCK hLock
);
262 inline void RWLockPreemptiveWriteLock(RWLOCK hLock
, DWORD dwTimeout
, DWORD dwSleep
)
264 while(!RWLockWriteLock(hLock
, dwTimeout
))
265 ThreadSleepMs(dwSleep
);