Krita Source Code Documentation
Loading...
Searching...
No Matches
qsbr.h
Go to the documentation of this file.
1/*------------------------------------------------------------------------
2 Junction: Concurrent data structures in C++
3 Copyright (c) 2016 Jeff Preshing
4 Distributed under the Simplified BSD License.
5 Original location: https://github.com/preshing/junction
6 This software is distributed WITHOUT ANY WARRANTY; without even the
7 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 See the LICENSE file for more information.
9------------------------------------------------------------------------*/
10
11#ifndef QSBR_H
12#define QSBR_H
13
14#include <kis_lockless_stack.h>
15
16#define CALL_MEMBER(obj, pmf) ((obj).*(pmf))
17
18class QSBR
19{
20private:
21 struct Action {
22 void (*func)(void*);
23 quint64 param[4]; // Size limit found experimentally. Verified by assert below.
24
25 Action() = default;
26
27 Action(void (*f)(void*), void* p, quint64 paramSize) : func(f)
28 {
29 KIS_ASSERT(paramSize <= sizeof(param)); // Verify size limit.
30 memcpy(&param, p, paramSize);
31 }
32
34 {
35 func(&param);
36 }
37 };
38
42
43 void releasePoolSafely(KisLocklessStack<Action> *pool, bool force = false) {
45 tmp.mergeFrom(*pool);
46 if (tmp.isEmpty()) return;
47
48 if (force || tmp.size() > 4096) {
49 while (m_rawPointerUsers.loadAcquire());
50
51 Action action;
52 while (tmp.pop(action)) {
53 action();
54 }
55 } else {
56 if (!m_rawPointerUsers.loadAcquire()) {
57 Action action;
58 while (tmp.pop(action)) {
59 action();
60 }
61 } else {
62 // push elements back to the source
63 pool->mergeFrom(tmp);
64 }
65 }
66 }
67
68public:
69
70 template <class T>
71 void enqueue(void (T::*pmf)(), T* target, bool migration = false)
72 {
73 struct Closure {
74 void (T::*pmf)();
75 T* target;
76
77 static void thunk(void* param)
78 {
79 Closure* self = (Closure*) param;
80 CALL_MEMBER(*self->target, self->pmf)();
81 }
82 };
83
84 Closure closure = {pmf, target};
85
86 if (migration) {
87 m_migrationReclaimActions.push(Action(Closure::thunk, &closure, sizeof(closure)));
88 } else {
89 m_pendingActions.push(Action(Closure::thunk, &closure, sizeof(closure)));
90 }
91 }
92
98
104
106 {
107 m_rawPointerUsers.ref();
108 }
109
111 {
112 m_rawPointerUsers.deref();
113 }
114
116 return m_rawPointerUsers.loadAcquire();
117 }
118};
119
120#endif // QSBR_H
const Params2D p
KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
void mergeFrom(KisLocklessStack< T > &other)
Definition qsbr.h:19
KisLocklessStack< Action > m_pendingActions
Definition qsbr.h:40
void releasePoolSafely(KisLocklessStack< Action > *pool, bool force=false)
Definition qsbr.h:43
void flush()
Definition qsbr.h:99
QAtomicInt m_rawPointerUsers
Definition qsbr.h:39
void lockRawPointerAccess()
Definition qsbr.h:105
bool sanityRawPointerAccessLocked() const
Definition qsbr.h:115
void enqueue(void(T::*pmf)(), T *target, bool migration=false)
Definition qsbr.h:71
KisLocklessStack< Action > m_migrationReclaimActions
Definition qsbr.h:41
void unlockRawPointerAccess()
Definition qsbr.h:110
void update()
Definition qsbr.h:93
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
#define CALL_MEMBER(obj, pmf)
Definition qsbr.h:16
quint64 param[4]
Definition qsbr.h:23
Action()=default
Action(void(*f)(void *), void *p, quint64 paramSize)
Definition qsbr.h:27
void operator()()
Definition qsbr.h:33
void(* func)(void *)
Definition qsbr.h:22