Added thread wrappers for GNU Pth
[public/netxms.git] / include / rwlock.h
CommitLineData
b8191466
VK
1/*
2** NetXMS - Network Management System
df7156b3
VK
3** NetXMS Foundation Library
4** Copyright (C) 2003, 2004, 2005, 2006 Victor Kirhenshtein
b8191466
VK
5**
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.
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**
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.
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
53inline BOOL RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut)
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
97inline BOOL RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut)
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
df7156b3 147#else /* HAVE_PTHREAD_RWLOCK */
b8191466
VK
148
149struct __rwlock_data
150{
a8cbc386
VK
151#ifdef _WIN32
152 HANDLE m_mutex;
153 HANDLE m_condRead;
154 HANDLE m_condWrite;
155#else
e86405b2 156 pthread_mutex_t m_mutex;
a8cbc386
VK
157 pthread_cond_t m_condRead;
158 pthread_cond_t m_condWrite;
159#endif
b8191466
VK
160 DWORD m_dwWaitReaders;
161 DWORD m_dwWaitWriters;
162 int m_iRefCount; // -1 for write lock, otherwise number of read locks
163};
164
165typedef struct __rwlock_data * RWLOCK;
166
df7156b3
VK
167RWLOCK LIBNETXMS_EXPORTABLE RWLockCreate(void);
168void LIBNETXMS_EXPORTABLE RWLockDestroy(RWLOCK hLock);
169BOOL LIBNETXMS_EXPORTABLE RWLockReadLock(RWLOCK hLock, DWORD dwTimeOut);
170BOOL LIBNETXMS_EXPORTABLE RWLockWriteLock(RWLOCK hLock, DWORD dwTimeOut);
171void LIBNETXMS_EXPORTABLE RWLockUnlock(RWLOCK hLock);
b8191466
VK
172
173#endif
174
175#endif