Initial commit (software version 0.2.0)
[movie-schedule] / src / utils / assertedlock.cpp
1 // Copyright 2010 Jochen Becher
2 //
3 // This file is part of MovieSchedule.
4 //
5 // MovieSchedule is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // MovieSchedule is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with MovieSchedule.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "assertedlock.h"
19
20 #include <QMutexLocker>
21 #include <QThread>
22
23 AssertedLock::AssertedLock()
24     :
25 #ifndef NDEBUG
26     _lock_counter(0),
27     _mutex(),
28 #endif
29     _lock(QReadWriteLock::Recursive)
30 {
31 }
32
33 AssertedLock::~AssertedLock()
34 {
35 #ifndef NDEBUG
36     QMutexLocker locker(&_mutex);
37     Q_ASSERT_X(_lock_counter == 0, __func__, "lock counter must be 0");
38 #endif
39 }
40
41 void AssertedLock::Lock(LockMode mode)
42 {
43 #ifndef NDEBUG
44     {
45         QMutexLocker locker(&_mutex);
46         if (GetLockCounter() > 0) {
47             if (GetLockMode() == READ) {
48                 if (mode != READ) {
49                     Q_ASSERT_X(mode == READ, __func__, "unable to change lockmode from READ to WRITE");
50                 }
51             } else {
52                 if (mode != WRITE) {
53                     mode = WRITE;
54                 }
55             }
56         } else {
57             SetLockMode(mode);
58         }
59         IncLockCounter();
60     }
61 #endif
62     if (mode == READ) {
63         _lock.lockForRead();
64     } else {
65         _lock.lockForWrite();
66     }
67 }
68
69 void AssertedLock::Unlock()
70 {
71 #ifndef NDEBUG
72     {
73         QMutexLocker locker(&_mutex);
74         Q_ASSERT_X(GetLockCounter() > 0, __func__, "too many unlocks");
75         DecLockCounter();
76     }
77 #endif
78     _lock.unlock();
79 }
80
81 #ifndef NDEBUG
82 AssertedLock::LockMode AssertedLock::GetLockMode() const
83 {
84     return _thread_data[QThread::currentThread()]._lock_mode;
85 }
86
87 void AssertedLock::SetLockMode(LockMode mode)
88 {
89     _thread_data[QThread::currentThread()]._lock_mode = mode;
90 }
91
92 int AssertedLock::GetLockCounter() const
93 {
94     return _thread_data[QThread::currentThread()]._lock_counter;
95 }
96
97 void AssertedLock::IncLockCounter()
98 {
99     _thread_data[QThread::currentThread()]._lock_counter += 1;
100     ++_lock_counter;
101 }
102
103 void AssertedLock::DecLockCounter()
104 {
105     _thread_data[QThread::currentThread()]._lock_counter -= 1;
106     --_lock_counter;
107 }
108
109 void AssertedLock::AssertLockedForMode(LockMode mode) const
110 {
111     QMutexLocker locker(&_mutex);
112     if (GetLockCounter() <= 0) {
113         Q_ASSERT_X(_lock_counter > 0, __func__, "expected lock");
114     }
115     if (GetLockMode() == READ) {
116         if (mode != READ) {
117             Q_ASSERT_X(mode == READ, __func__, "locked for READ but WRITE lock expected");
118         }
119     }
120 }
121
122 void AssertedLock::AssertNotLocked() const
123 {
124     QMutexLocker locker(&_mutex);
125     Q_ASSERT_X(GetLockCounter() == 0, __func__, "unexpected lock.");
126 }
127 #endif