Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_lock_free_cache.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#ifndef __KIS_CACHE_STATE_VALUE_H
8#define __KIS_CACHE_STATE_VALUE_H
9
10#include <QAtomicInt>
11
20{
21 static const int WritersCountMask = 0x00FF;
22 static const int WritersCountIncrement = 0x0001;
23 static const int IsValidMask = 0x0100;
24 static const int SeqNoMask = ~(WritersCountMask | IsValidMask);
25 static const int SeqNoIncrement = 0x0200;
26public:
27 typedef int SeqValue;
28public:
29 inline void invalidate() {
30 int oldValue;
31 int newValue = -1;
32 do {
33 oldValue = m_value;
34 newValue = incrementSeqNo(oldValue) & ~IsValidMask;
35 } while(!m_value.testAndSetOrdered(oldValue, newValue));
36 }
37
38 inline bool startRead(int *seq) const {
39 *seq = m_value;
40
41 return (*seq & IsValidMask) &&
42 !(*seq & WritersCountMask);
43 }
44
45 inline bool endRead(int seq) const {
46 bool result = seq == m_value;
47 return result;
48 }
49
50
51 inline bool startWrite(int *seq) {
52 int oldValue;
53 int newValue;
54 do {
55 oldValue = m_value;
56 if ((oldValue & IsValidMask) ||
57 (oldValue & WritersCountMask)) {
58
59 return false;
60 }
61 newValue = incrementSeqNo(oldValue) + WritersCountIncrement;
62 } while(!m_value.testAndSetOrdered(oldValue, newValue));
63
64 *seq = newValue;
65 return true;
66 }
67
68 inline void endWrite(int seq) {
69 int oldValue;
70 int newValue;
71 do {
72 oldValue = m_value;
73
74 if (oldValue == seq) {
75 newValue = (incrementSeqNo(oldValue) - WritersCountIncrement) | IsValidMask;
76 } else {
77 newValue = (incrementSeqNo(oldValue) - WritersCountIncrement) & ~IsValidMask;
78 }
79 } while(!m_value.testAndSetOrdered(oldValue, newValue));
80 }
81
82private:
84 // handle overflow properly
85 if ((value & SeqNoMask) == SeqNoMask) {
86 value = value & ~SeqNoMask;
87 } else {
89 }
90 return value;
91 }
92
93private:
94 QAtomicInt m_value;
95};
96
97template <typename T>
99{
100public:
101 virtual ~KisLockFreeCache() {}
102
106 void invalidate() {
108 }
109
113 T getValue() const {
115 bool isValid = false;
116 T savedValue;
117
118 if (m_state.startRead(&seqValue)) {
119 savedValue = m_value;
120 isValid = m_state.endRead(seqValue);
121 }
122
123 if (isValid) {
124 return savedValue;
125 } else if (m_state.startWrite(&seqValue)) {
126 savedValue = calculateNewValue();
127 m_value = savedValue;
128 m_state.endWrite(seqValue);
129 return savedValue;
130 } else {
131 return calculateNewValue();
132 }
133 }
134
135 bool tryGetValue(T &result) const {
137 bool isValid = false;
138 T savedValue;
139
140 if (m_state.startRead(&seqValue)) {
141 savedValue = m_value;
142 isValid = m_state.endRead(seqValue);
143 }
144
145 if (isValid) {
146 result = savedValue;
147 }
148
149 return isValid;
150 }
151
152protected:
157 virtual T calculateNewValue() const = 0;
158
159private:
161 mutable T m_value;
162};
163
164template <typename T, typename Mode>
166{
167public:
171
175 void invalidate() {
177 }
178
182 T getValue(Mode mode) const {
184 bool isValid = false;
185 T savedValue;
186 Mode savedMode;
187
188 if (m_state.startRead(&seqValue)) {
189 savedValue = m_value;
190 savedMode = m_mode;
191 isValid = m_state.endRead(seqValue);
192 isValid &= savedMode == mode;
193 }
194
195 if (isValid) {
196 return savedValue;
197 } else if (m_state.startWrite(&seqValue)) {
198 savedValue = calculateNewValue();
199 m_value = savedValue;
200 m_mode = mode;
201 m_state.endWrite(seqValue);
202 return savedValue;
203 } else {
204 return calculateNewValue();
205 }
206 }
207
208 bool tryGetValue(T &result, Mode mode) const {
210 bool isValid = false;
211 T newValue;
212 Mode savedMode;
213
214 if (m_state.startRead(&seqValue)) {
215 newValue = m_value;
216 savedMode = m_mode;
217 isValid = m_state.endRead(seqValue);
218 isValid &= savedMode == mode;
219 }
220
221 if (isValid) {
222 result = newValue;
223 }
224
225 return isValid;
226 }
227
228protected:
233 virtual T calculateNewValue() const = 0;
234
235private:
237 mutable T m_value;
238 mutable Mode m_mode;
239};
240
241
242
243#endif /* __KIS_CACHE_STATE_VALUE_H */
float value(const T *src, size_t ch)
int incrementSeqNo(int value)
bool endRead(int seq) const
static const int SeqNoMask
static const int SeqNoIncrement
static const int IsValidMask
static const int WritersCountMask
static const int WritersCountIncrement
bool startWrite(int *seq)
bool startRead(int *seq) const
bool tryGetValue(T &result, Mode mode) const
virtual T calculateNewValue() const =0
bool tryGetValue(T &result) const
virtual T calculateNewValue() const =0
KisCacheStateValue m_state