Revised OpenFlow Library  v0.6.0dev
 All Classes Files Functions Variables Friends Groups Pages
thread_helper.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /*
6  * thread_helper.h
7  *
8  * Created on: Jan 9, 2012
9  * Author: tobi
10  */
11 
12 #ifndef THREAD_HELPER_H_
13 #define THREAD_HELPER_H_
14 
15 #include <pthread.h>
16 #include <inttypes.h>
17 
18 #include "croflexception.h"
19 
20 namespace rofl
21 {
22 
23 class RwLock; // forward declaration
24 
26  pthread_rwlock_t rwlock;
27  friend class RwLock;
28 public:
29  PthreadRwLock(pthread_rwlockattr_t *attr = NULL) {
30  pthread_rwlock_init(&rwlock, attr);
31  };
32  ~PthreadRwLock() {
33  pthread_rwlock_destroy(&rwlock);
34  }
35 };
36 
37 
38 class eLockBase : public RoflException {
39 public:
40  eLockBase(const std::string& __arg) : RoflException(__arg) {};
41 };
42 
43 class eLockInval : public eLockBase {
44 public:
45  eLockInval(const std::string& __arg) : eLockBase(__arg) {};
46 };
47 
48 class eLockWouldBlock : public eLockBase {
49 public:
50  eLockWouldBlock(const std::string& __arg) : eLockBase(__arg) {};
51 };
52 
53 class Lock
54 {
55 public:
56  Lock(pthread_mutex_t *mutex, bool blocking = true) throw (eLockWouldBlock) :
57  mutex(mutex), locked(false)
58  {
59  if (blocking) {
60  pthread_mutex_lock(this->mutex);
61  } else {
62  if (pthread_mutex_trylock(this->mutex) < 0) {
63  switch (errno) {
64  case EBUSY:
65  throw eLockWouldBlock("Lock::Lock() pthread_mutex_trylock");
66  default:
67  throw eSysCall("pthread_mutex_trylock failed");
68  }
69  }
70  }
71  locked = true;
72  }
73 
74  virtual
75  ~Lock()
76  {
77  if (locked) {
78  pthread_mutex_unlock(this->mutex);
79  }
80  }
81 
82 private:
83  pthread_mutex_t *mutex;
84  bool locked;
85 };
86 
87 
88 class RwLock
89 {
90  pthread_rwlock_t *rwlock;
91  bool locked;
92 public:
93 
94  enum rwlock_rwtype_t {
95  RWLOCK_READ = 1,
96  RWLOCK_WRITE = 2,
97  };
98 
102  RwLock(pthread_rwlock_t *rwlock,
103  uint8_t rwtype = RWLOCK_WRITE, // safe option: lock for writing
104  bool blocking = true) throw (eLockWouldBlock, eLockInval) :
105  rwlock(rwlock), locked(false)
106  {
107  if (blocking) {
108  switch (rwtype) {
109  case RWLOCK_READ:
110  pthread_rwlock_rdlock(rwlock);
111  break;
112  case RWLOCK_WRITE:
113  pthread_rwlock_wrlock(rwlock);
114  break;
115  default:
116  throw eLockInval("RwLock::RwLock() invalid locking type");
117  }
118  } else {
119  int rc = 0;
120 
121  switch (rwtype) {
122  case RWLOCK_READ:
123  rc = pthread_rwlock_tryrdlock(rwlock);
124  break;
125  case RWLOCK_WRITE:
126  rc = pthread_rwlock_trywrlock(rwlock);
127  break;
128  default:
129  throw eLockInval("RwLock::RwLock() invalid locking type");
130  }
131 
132  if (rc < 0) {
133  switch (errno) {
134  case EBUSY:
135  throw eLockWouldBlock("RwLock::RwLock() pthread_mutex_trylock");
136 
137  default:
138  throw eSysCall("pthread_mutex_trylock failed");
139  }
140  }
141  }
142  locked = true;
143  };
144 
148  RwLock(PthreadRwLock& pthreadRwLock,
149  uint8_t rwtype = RWLOCK_WRITE, // safe option: lock for writing
150  bool blocking = true) throw (eLockWouldBlock, eLockInval) :
151  rwlock(&(pthreadRwLock.rwlock)), locked(false)
152  {
153  if (blocking) {
154  switch (rwtype) {
155  case RWLOCK_READ:
156  pthread_rwlock_rdlock(rwlock);
157  break;
158  case RWLOCK_WRITE:
159  pthread_rwlock_wrlock(rwlock);
160  break;
161  default:
162  throw eLockInval("RwLock::RwLock() invalid locking type");
163  }
164  } else {
165  int rc = 0;
166 
167  switch (rwtype) {
168  case RWLOCK_READ:
169  rc = pthread_rwlock_tryrdlock(rwlock);
170  break;
171  case RWLOCK_WRITE:
172  rc = pthread_rwlock_trywrlock(rwlock);
173  break;
174  default:
175  throw eLockInval("RwLock::RwLock() invalid locking type");
176  }
177 
178  if (rc < 0) {
179  switch (errno) {
180  case EBUSY:
181  throw eLockWouldBlock("RwLock::RwLock() pthread_mutex_trylock");
182 
183  default:
184  throw eSysCall("pthread_rwlock_trylock failed");
185  }
186  }
187  }
188  locked = true;
189  };
190 
191 
192 
196  virtual
198  {
199  if (locked) {
200  pthread_rwlock_unlock(rwlock);
201  }
202  }
203 };
204 
205 }; // end of namespace
206 
207 #endif /* THREAD_HELPER_H_ */
Definition: thread_helper.h:48
Definition: thread_helper.h:53
virtual ~RwLock()
Definition: thread_helper.h:197
Definition: thread_helper.h:25
Definition: thread_helper.h:38
RwLock(pthread_rwlock_t *rwlock, uint8_t rwtype=RWLOCK_WRITE, bool blocking=true)
Definition: thread_helper.h:102
Definition: thread_helper.h:88
RwLock(PthreadRwLock &pthreadRwLock, uint8_t rwtype=RWLOCK_WRITE, bool blocking=true)
Definition: thread_helper.h:148
Definition: thread_helper.h:43
Definition: croflexception.h:40
Definition: croflexception.h:27