Line data Source code
1 : /// ReadWriteLock.hpp
2 : ///
3 : /// @author Paul Grenz
4 : ///
5 : ////////////////////////////////////////////////////////////////////////////////
6 :
7 : #ifndef PCF_READ_WRITE_LOCK_HPP
8 : #define PCF_READ_WRITE_LOCK_HPP
9 :
10 : #include <stdexcept>
11 : #include <pthread.h>
12 : #include <string.h>
13 :
14 : ////////////////////////////////////////////////////////////////////////////////
15 :
16 : namespace pcf
17 : {
18 : class ReadWriteLock
19 : {
20 : public:
21 : // This is a wrapper class for a read lock which will unlock when
22 : // the class goes out of scope.
23 : // todo: migrate it to its own file.
24 : class AutoRLock
25 : {
26 : private:
27 : // This is private so the class may not be instantiated this way.
28 : AutoRLock()
29 : {
30 : m_rwlock = NULL;
31 : }
32 : public:
33 3411 : AutoRLock( ReadWriteLock *rwlock )
34 3411 : {
35 3411 : m_rwlock = rwlock;
36 3411 : if ( m_rwlock == NULL )
37 0 : throw std::invalid_argument( "Read-write lock pointer is NULL" );
38 3411 : m_rwlock->lockRead();
39 3411 : }
40 3411 : ~AutoRLock()
41 : {
42 3411 : if ( m_rwlock != NULL )
43 3411 : m_rwlock->unlockRead();
44 3411 : }
45 : private:
46 : ReadWriteLock *m_rwlock;
47 : };
48 : // This is a wrapper class for a write lock which will unlock when
49 : // the class goes out of scope.
50 : // todo: migrate it to its own file.
51 : class AutoWLock
52 : {
53 : private:
54 : // This is private so the class may not be instantiated this way.
55 : AutoWLock()
56 : {
57 : m_rwlock = NULL;
58 : }
59 : public:
60 11038 : AutoWLock( ReadWriteLock *rwlock )
61 11038 : {
62 11038 : m_rwlock = rwlock;
63 11038 : if ( m_rwlock == NULL )
64 0 : throw std::invalid_argument( "Read-write lock pointer is NULL" );
65 11038 : m_rwlock->lockWrite();
66 11038 : }
67 11038 : ~AutoWLock()
68 : {
69 11038 : if ( m_rwlock != NULL )
70 11038 : m_rwlock->unlockWrite();
71 11038 : }
72 : private:
73 : ReadWriteLock *m_rwlock;
74 : };
75 :
76 : // Constructor/destructor/operators.
77 : public:
78 17980 : ReadWriteLock()
79 17980 : {
80 17980 : int nErr = 0;
81 17980 : if ( ( nErr = pthread_rwlock_init( &m_idLock, NULL ) ) != 0 )
82 0 : throw std::runtime_error( std::string( "ReadWriteLock: " ) + strerror( nErr ) );
83 17980 : }
84 17932 : virtual ~ReadWriteLock() noexcept(false)
85 17932 : {
86 17932 : int nErr = 0;
87 17932 : if ( ( nErr = pthread_rwlock_destroy( &m_idLock ) ) != 0 )
88 0 : throw std::runtime_error( std::string( "ReadWriteLock: " ) + strerror( nErr ) );
89 17932 : }
90 :
91 : private:
92 : ReadWriteLock( const ReadWriteLock & )
93 : {
94 : }
95 : const ReadWriteLock &operator =( const ReadWriteLock & )
96 : {
97 : return *this;
98 : }
99 :
100 : // Methods.
101 : public:
102 3411 : void lockRead()
103 : {
104 3411 : int nErr = 0;
105 3411 : if ( ( nErr = pthread_rwlock_rdlock( &m_idLock ) ) != 0 )
106 0 : throw std::runtime_error( std::string( "lockRead: " ) + strerror( nErr ) );
107 3411 : }
108 11038 : void lockWrite()
109 : {
110 11038 : int nErr = 0;
111 11038 : if ( ( nErr = pthread_rwlock_wrlock( &m_idLock ) ) != 0 )
112 0 : throw std::runtime_error( std::string( "lockWrite: " ) + strerror( nErr ) );
113 11038 : }
114 3411 : void unlockRead()
115 : {
116 3411 : int nErr = 0;
117 3411 : if ( ( nErr = pthread_rwlock_unlock( &m_idLock ) ) != 0 )
118 0 : throw std::runtime_error( std::string( "unlockRead: " ) + strerror( nErr ) );
119 3411 : }
120 11038 : void unlockWrite()
121 : {
122 11038 : int nErr = 0;
123 11038 : if ( ( nErr = pthread_rwlock_unlock( &m_idLock ) ) != 0 )
124 0 : throw std::runtime_error( std::string( "unlockWrite: " ) + strerror( nErr ) );
125 11038 : }
126 :
127 : // Variables.
128 : private:
129 : /// id or handle of the ReadWriteLock created.
130 : pthread_rwlock_t m_idLock;
131 :
132 : }; // Class ReadWriteLock
133 : } // Namespace pcf
134 :
135 : ////////////////////////////////////////////////////////////////////////////////
136 :
137 : #endif // PCF_READ_WRITE_LOCK_HPP
|