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 1829 : AutoRLock( ReadWriteLock *rwlock )
34 1829 : {
35 1829 : m_rwlock = rwlock;
36 1829 : if ( m_rwlock == NULL )
37 0 : throw std::invalid_argument( "Read-write lock pointer is NULL" );
38 1829 : m_rwlock->lockRead();
39 1829 : }
40 1829 : ~AutoRLock()
41 : {
42 1829 : if ( m_rwlock != NULL )
43 1829 : m_rwlock->unlockRead();
44 1829 : }
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 8685 : AutoWLock( ReadWriteLock *rwlock )
61 8685 : {
62 8685 : m_rwlock = rwlock;
63 8685 : if ( m_rwlock == NULL )
64 0 : throw std::invalid_argument( "Read-write lock pointer is NULL" );
65 8685 : m_rwlock->lockWrite();
66 8685 : }
67 8685 : ~AutoWLock()
68 : {
69 8685 : if ( m_rwlock != NULL )
70 8685 : m_rwlock->unlockWrite();
71 8685 : }
72 : private:
73 : ReadWriteLock *m_rwlock;
74 : };
75 :
76 : // Constructor/destructor/operators.
77 : public:
78 8122 : ReadWriteLock()
79 8122 : {
80 8122 : int nErr = 0;
81 8122 : if ( ( nErr = pthread_rwlock_init( &m_idLock, NULL ) ) != 0 )
82 0 : throw std::runtime_error( std::string( "ReadWriteLock: " ) + strerror( nErr ) );
83 8122 : }
84 8122 : virtual ~ReadWriteLock() noexcept(false)
85 8122 : {
86 8122 : int nErr = 0;
87 8122 : if ( ( nErr = pthread_rwlock_destroy( &m_idLock ) ) != 0 )
88 0 : throw std::runtime_error( std::string( "ReadWriteLock: " ) + strerror( nErr ) );
89 8122 : }
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 1829 : void lockRead()
103 : {
104 1829 : int nErr = 0;
105 1829 : if ( ( nErr = pthread_rwlock_rdlock( &m_idLock ) ) != 0 )
106 0 : throw std::runtime_error( std::string( "lockRead: " ) + strerror( nErr ) );
107 1829 : }
108 8685 : void lockWrite()
109 : {
110 8685 : int nErr = 0;
111 8685 : if ( ( nErr = pthread_rwlock_wrlock( &m_idLock ) ) != 0 )
112 0 : throw std::runtime_error( std::string( "lockWrite: " ) + strerror( nErr ) );
113 8685 : }
114 1829 : void unlockRead()
115 : {
116 1829 : int nErr = 0;
117 1829 : if ( ( nErr = pthread_rwlock_unlock( &m_idLock ) ) != 0 )
118 0 : throw std::runtime_error( std::string( "unlockRead: " ) + strerror( nErr ) );
119 1829 : }
120 8685 : void unlockWrite()
121 : {
122 8685 : int nErr = 0;
123 8685 : if ( ( nErr = pthread_rwlock_unlock( &m_idLock ) ) != 0 )
124 0 : throw std::runtime_error( std::string( "unlockWrite: " ) + strerror( nErr ) );
125 8685 : }
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
|