change log updated
[public/netxms.git] / include / rwlock.h
CommitLineData
b8191466
VK
1/*
2** NetXMS - Network Management System
df7156b3 3** NetXMS Foundation Library
68f384ea 4** Copyright (C) 2003-2010 Victor Kirhenshtein
b8191466
VK
5**
6** This program is free software; you can redistribute it and/or modify
68f384ea
VK
7** it under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation; either version 3 of the License, or
b8191466
VK
9** (at your option) any later version.
10**
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.
15**
68f384ea 16** You should have received a copy of the GNU Lesser General Public License
b8191466
VK
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
df7156b3 20** File: rwlock.h
b8191466
VK
21**
22**/
23
24#ifndef _rwlock_h_
25#define _rwlock_h_
26
b8191466
VK
27#if HAVE_PTHREAD_RWLOCK
28
29typedef pthread_rwlock_t * RWLOCK;
30
31inline RWLOCK RWLockCreate(void)
32{
33 RWLOCK hLock;
34
35 hLock = (RWLOCK)malloc(sizeof(pthread_rwlock_t));
36 if (pthread_rwlock_init(hLock, NULL) != 0)
37 {
38 free(hLock);
39 hLock = NULL;
40 }
41 return hLock;
42}
43
44inline void RWLockDestroy(RWLOCK hLock)
45{
46 if (hLock != NULL)
47 {
48 pthread_rwlock_destroy(hLock);
49 free(hLock);
50 }
51}
52
967893bb 53inline BOOL RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut)
b8191466 54{
b8191466
VK
55 BOOL ret = FALSE;
56
57 if (hLock != NULL)
58 {
59 if (dwTimeOut == INFINITE)
60 {
61 if (pthread_rwlock_rdlock(hLock) == 0)
62 {
63 ret = TRUE;
64 }
65 }
66 else
67 {
df7156b3
VK
68#if HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
69 struct timeval now;
70 struct timespec timeout;
71
72 // FIXME: there should be more accurate way
73 gettimeofday(&now, NULL);
74 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
75
76 now.tv_usec += (dwTimeOut % 1000) * 1000;
77 timeout.tv_sec += now.tv_usec / 1000000;
78 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
79
6e31cf89 80 ret = (pthread_rwlock_timedrdlock(hLock, &timeout) == 0);
df7156b3
VK
81#else
82 for(int i = (dwTimeOut / 50) + 1; i > 0; i--)
b8191466
VK
83 {
84 if (pthread_rwlock_tryrdlock(hLock) == 0)
85 {
86 ret = TRUE;
87 break;
88 }
89 ThreadSleepMs(50);
90 }
df7156b3 91#endif
b8191466
VK
92 }
93 }
94 return ret;
95}
96
967893bb 97inline BOOL RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut)
b8191466 98{
b8191466
VK
99 BOOL ret = FALSE;
100
101 if (hLock != NULL)
102 {
103 if (dwTimeOut == INFINITE)
104 {
105 if (pthread_rwlock_wrlock(hLock) == 0)
106 {
107 ret = TRUE;
108 }
109 }
110 else
111 {
df7156b3
VK
112#if HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
113 struct timeval now;
114 struct timespec timeout;
115
116 // FIXME: there should be more accurate way
117 gettimeofday(&now, NULL);
118 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
119
120 now.tv_usec += (dwTimeOut % 1000) * 1000;
121 timeout.tv_sec += now.tv_usec / 1000000;
122 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
123
6e31cf89 124 ret = (pthread_rwlock_timedwrlock(hLock, &timeout) == 0);
df7156b3
VK
125#else
126 for(int i = (dwTimeOut / 50) + 1; i > 0; i--)
b8191466
VK
127 {
128 if (pthread_rwlock_trywrlock(hLock) == 0)
129 {
130 ret = TRUE;
131 break;
132 }
133 ThreadSleepMs(50);
134 }
df7156b3 135#endif
b8191466
VK
136 }
137 }
138 return ret;
139}
140
141inline void RWLockUnlock(RWLOCK hLock)
142{
143 if (hLock != NULL)
144 pthread_rwlock_unlock(hLock);
145}
146
16df1dcb
VK
147#elif defined(_USE_GNU_PTH)
148
149typedef pth_rwlock_t * RWLOCK;
150
151inline RWLOCK RWLockCreate(void)
152{
153 RWLOCK hLock;
154
155 hLock = (RWLOCK)malloc(sizeof(pth_rwlock_t));
156 if (!pth_rwlock_init(hLock))
157 {
158 free(hLock);
159 hLock = NULL;
160 }
161 return hLock;
162}
163
164inline void RWLockDestroy(RWLOCK hLock)
165{
166 if (hLock != NULL)
167 {
168 free(hLock);
169 }
170}
171
967893bb 172inline BOOL RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut)
16df1dcb
VK
173{
174 BOOL ret = FALSE;
175
176 if (hLock != NULL)
177 {
178 if (dwTimeOut == INFINITE)
179 {
180 if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RD, FALSE, NULL))
181 {
182 ret = TRUE;
183 }
184 }
185 else
186 {
187 pth_event_t ev;
188
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))
191 {
192 ret = TRUE;
193 }
194 pth_event_free(ev, PTH_FREE_ALL);
195 }
196 }
197 return ret;
198}
199
967893bb 200inline BOOL RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut)
16df1dcb
VK
201{
202 BOOL ret = FALSE;
203
204 if (hLock != NULL)
205 {
206 if (dwTimeOut == INFINITE)
207 {
208 if (pth_rwlock_acquire(hLock, PTH_RWLOCK_RW, FALSE, NULL))
209 {
210 ret = TRUE;
211 }
212 }
213 else
214 {
215 pth_event_t ev;
216
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))
219 {
220 ret = TRUE;
221 }
222 pth_event_free(ev, PTH_FREE_ALL);
223 }
224 }
225 return ret;
226}
227
228inline void RWLockUnlock(RWLOCK hLock)
229{
230 if (hLock != NULL)
231 pth_rwlock_release(hLock);
232}
233
234#else /* not HAVE_PTHREAD_RWLOCK and not defined _USE_GNU_PTH */
b8191466
VK
235
236struct __rwlock_data
237{
a8cbc386
VK
238#ifdef _WIN32
239 HANDLE m_mutex;
240 HANDLE m_condRead;
241 HANDLE m_condWrite;
242#else
e86405b2 243 pthread_mutex_t m_mutex;
a8cbc386
VK
244 pthread_cond_t m_condRead;
245 pthread_cond_t m_condWrite;
246#endif
967893bb
VK
247 UINT32 m_dwWaitReaders;
248 UINT32 m_dwWaitWriters;
b8191466
VK
249 int m_iRefCount; // -1 for write lock, otherwise number of read locks
250};
251
252typedef struct __rwlock_data * RWLOCK;
253
7c521895 254RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate();
df7156b3 255void LIBNETXMS_EXPORTABLE RWLockDestroy(RWLOCK hLock);
967893bb
VK
256BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, UINT32 dwTimeOut);
257BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, UINT32 dwTimeOut);
df7156b3 258void LIBNETXMS_EXPORTABLE RWLockUnlock(RWLOCK hLock);
b8191466
VK
259
260#endif
261
967893bb 262inline void RWLockPreemptiveWriteLock(RWLOCK hLock, UINT32 dwTimeout, UINT32 dwSleep)
7c521895
VK
263{
264 while(!RWLockWriteLock(hLock, dwTimeout))
265 ThreadSleepMs(dwSleep);
266}
267
b8191466 268#endif