aboutsummaryrefslogtreecommitdiff
path: root/src/unstable
diff options
context:
space:
mode:
Diffstat (limited to 'src/unstable')
-rw-r--r--src/unstable/readwritemutex.cpp78
-rw-r--r--src/unstable/readwritemutex.h75
2 files changed, 153 insertions, 0 deletions
diff --git a/src/unstable/readwritemutex.cpp b/src/unstable/readwritemutex.cpp
new file mode 100644
index 0000000..b0a3b77
--- /dev/null
+++ b/src/unstable/readwritemutex.cpp
@@ -0,0 +1,78 @@
1#include "bu/readwritemutex.h"
2
3Bu::ReadWriteMutex::ReadWriteMutex() :
4 iCounter( 0 ),
5 bWantWrite( false )
6{
7}
8
9Bu::ReadWriteMutex::~ReadWriteMutex()
10{
11}
12
13void Bu::ReadWriteMutex::lockRead()
14{
15 // Check to see if someone wants to write
16 cWrite.lock();
17 if( bWantWrite )
18 {
19 // If so, wait patiently for them to finish
20 cWrite.wait();
21 }
22 cWrite.unlock();
23
24 // Now lock the read counter
25 mRead.lock();
26 iCounter++;
27 // If the lock counter is one, we just locked for the first time,
28 // so we lock the writer.
29 if( iCounter == 1 )
30 mWrite.lock();
31 mRead.unlock();
32}
33
34void Bu::ReadWriteMutex::unlockRead()
35{
36 // Lock the read counter
37 mRead.lock();
38 iCounter--;
39 // If we just decremented the counter back to zero then we can
40 // release the write lock
41 if( iCounter == 0 )
42 mWrite.unlock();
43 mRead.unlock();
44}
45
46void Bu::ReadWriteMutex::lockWrite()
47{
48 // Lock the read counter
49 mRead.lock();
50 if( iCounter > 0 )
51 {
52 // If there is an active read in progress then we set the bWantWrite
53 // flag to make sure no more readers start working.
54 cWrite.lock();
55 bWantWrite = true;
56 cWrite.unlock();
57 }
58 mRead.unlock();
59
60 // Lock the write lock
61 mWrite.lock();
62}
63
64void Bu::ReadWriteMutex::unlockWrite()
65{
66 // Just always set the bWantWrite flag to false at this point, as long
67 // as we're locked.
68 cWrite.lock();
69 bWantWrite = false;
70 cWrite.unlock();
71
72 // Release all waiting readers, they won't actually do much until we
73 // unlock the write lock though
74 cWrite.broadcast();
75
76 // Unlock the write lock
77 mWrite.unlock();
78}
diff --git a/src/unstable/readwritemutex.h b/src/unstable/readwritemutex.h
new file mode 100644
index 0000000..9e07047
--- /dev/null
+++ b/src/unstable/readwritemutex.h
@@ -0,0 +1,75 @@
1#ifndef BU_READ_WRITE_MUTEX_H
2#define BU_READ_WRITE_MUTEX_H
3
4#include "bu/mutex.h"
5#include "bu/condition.h"
6
7namespace Bu
8{
9 /**
10 * Mutex designed for situations where overlapped reading is safe, but
11 * overlapped writing isn't. There are many, many good examples of this
12 * including most data structures, streams, etc. etc.
13 *
14 * Use this just like a normal mutex except that you use the
15 * lockRead/unlockRead and lockWrite/unlockWrite functions depending on
16 * weather the section of code your locking is reading data or changing
17 * data.
18 *
19 * This particular mutex is designed so that while a read operation is
20 * happening other read operations can also happen, but no write operations
21 * can occur. While a write is happening, no other write or read operation
22 * can continue. There is an extra feature to ensure writes get a chance
23 * to complete, when a lockWrite is issued, all current read operations
24 * continue, but future read operations block until the write is complete.
25 */
26 class ReadWriteMutex
27 {
28 public:
29 ReadWriteMutex();
30 virtual ~ReadWriteMutex();
31
32 /**
33 * Lock the mutex for reading. Multiple code sections can hold a read
34 * lock at the same time, but write locks will wait for all read locks
35 * to be released before continuing. Read locks will also wait if
36 * there is an active write lock.
37 *
38 * It is very important to not make any changes to your data within
39 * a read lock.
40 */
41 void lockRead();
42
43 /**
44 * Release a read lock.
45 */
46 void unlockRead();
47
48 /**
49 * Lock the mutex for writing. Only one code section can have a write
50 * lock at any given time. No code sections can be in a locked read
51 * section while a write lock is held. When a write lock is requested
52 * all following read locks will block until the write operation is
53 * started, ensuring writes always get a chance to execute.
54 *
55 * Within a write locked code section feel free to change your data
56 * and read your data. It is imparative to spend as little time as
57 * possible in a write-locked section.
58 */
59 void lockWrite();
60
61 /**
62 * Release a write lock.
63 */
64 void unlockWrite();
65
66 private:
67 Bu::Mutex mRead;
68 int iCounter;
69 Bu::Mutex mWrite;
70 Bu::Condition cWrite;
71 bool bWantWrite;
72 };
73};
74
75#endif