|
43 | 43 | //---------------------------------------------------------------------------------- |
44 | 44 |
|
45 | 45 | #include "PythonQtPythonInclude.h" |
46 | | -#include <QList> |
| 46 | +#include <vector> |
| 47 | +#include <QVariant> |
47 | 48 |
|
48 | | -#define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \ |
49 | | -{ type* item = (type*)store.nextValuePtr(); \ |
| 49 | +#define PYTHONQT_MAX_ARGS 32 |
| 50 | + |
| 51 | +#define PythonQtArgumentFrame_ADD_VALUE(store, type, value, ptr) \ |
| 52 | +{ type* item = (type*)store->nextPODPtr(); \ |
50 | 53 | *item = value; \ |
51 | 54 | ptr = (void*)item; \ |
52 | 55 | } |
53 | 56 |
|
54 | | -#define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \ |
| 57 | +#define PythonQtArgumentFrame_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \ |
55 | 58 | { \ |
56 | | - type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \ |
| 59 | + type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store->nextPODPtr()); \ |
57 | 60 | *item = value; \ |
58 | 61 | ptr = (void*)item; \ |
59 | 62 | } |
60 | 63 |
|
61 | | -//! stores a position in the PythonQtValueStorage |
62 | | -class PythonQtValueStoragePosition { |
63 | | - |
64 | | -public: |
65 | | - PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; } |
| 64 | +#define PythonQtArgumentFrame_ADD_VARIANT_VALUE(store, value, ptr) \ |
| 65 | +{ QVariant* item = store->nextVariantPtr(); \ |
| 66 | + *item = value; \ |
| 67 | + ptr = (void*)item; \ |
| 68 | +} |
66 | 69 |
|
67 | | - int chunkIdx; |
68 | | - int chunkOffset; |
| 70 | +#define PythonQtArgumentFrame_ADD_VARIANT_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, value, ptr) \ |
| 71 | +{ \ |
| 72 | + QVariant* item = (QVariant*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store->nextVariantPtr()); \ |
| 73 | + *item = value; \ |
| 74 | + ptr = (void*)item; \ |
| 75 | +} |
69 | 76 |
|
70 | | -}; |
| 77 | +//! Stores C++ arguments for a qt_metacall (which are created when converting data from Python to C++) |
| 78 | +class PythonQtArgumentFrame { |
71 | 79 |
|
72 | | -//! a helper class that stores basic C++ value types in chunks |
73 | | -template <typename T, int chunkEntries> class PythonQtValueStorage |
74 | | -{ |
75 | 80 | public: |
76 | | - PythonQtValueStorage() { |
77 | | - _chunkIdx = 0; |
78 | | - _chunkOffset = 0; |
79 | | - _currentChunk = new T[chunkEntries]; |
80 | | - _chunks.append(_currentChunk); |
81 | | - }; |
82 | | - |
83 | | - //! clear all memory |
84 | | - void clear() { |
85 | | - T* chunk; |
86 | | - Q_FOREACH(chunk, _chunks) { |
87 | | - delete[]chunk; |
88 | | - } |
89 | | - _chunks.clear(); |
90 | | - } |
91 | | - |
92 | | - //! get the current position to be restored with setPos |
93 | | - void getPos(PythonQtValueStoragePosition & pos) { |
94 | | - pos.chunkIdx = _chunkIdx; |
95 | | - pos.chunkOffset = _chunkOffset; |
96 | | - } |
97 | | - |
98 | | - //! set the current position (without freeing memory, thus caching old entries for reuse) |
99 | | - void setPos(const PythonQtValueStoragePosition& pos) { |
100 | | - _chunkOffset = pos.chunkOffset; |
101 | | - if (_chunkIdx != pos.chunkIdx) { |
102 | | - _chunkIdx = pos.chunkIdx; |
103 | | - _currentChunk = _chunks.at(_chunkIdx); |
104 | | - } |
105 | | - } |
106 | | - |
107 | | - //! add one default constructed value and return the pointer to it |
108 | | - T* nextValuePtr() { |
109 | | - if (_chunkOffset>=chunkEntries) { |
110 | | - _chunkIdx++; |
111 | | - if (_chunkIdx >= _chunks.size()) { |
112 | | - T* newChunk = new T[chunkEntries]; |
113 | | - _chunks.append(newChunk); |
114 | | - _currentChunk = newChunk; |
115 | | - } else { |
116 | | - _currentChunk = _chunks.at(_chunkIdx); |
117 | | - } |
118 | | - _chunkOffset = 0; |
119 | | - } |
120 | | - T* newEntry = _currentChunk + _chunkOffset; |
121 | | - _chunkOffset++; |
122 | | - return newEntry; |
123 | | - }; |
124 | | - |
125 | | -protected: |
126 | | - QList<T*> _chunks; |
127 | | - |
128 | | - int _chunkIdx; |
129 | | - int _chunkOffset; |
130 | | - T* _currentChunk; |
| 81 | + //! Create a new (empty) frame (which is typically reused from a freelist) |
| 82 | + static PythonQtArgumentFrame* newFrame(); |
| 83 | + //! Frees the frame (resetting it and putting it back to the freelist) |
| 84 | + static void deleteFrame(PythonQtArgumentFrame* frame); |
131 | 85 |
|
132 | | -}; |
| 86 | + //! Frees all PythonQtArgumentFrame frames that are stored. |
| 87 | + static void cleanupFreeList(); |
133 | 88 |
|
134 | | -//! a helper class that stores basic C++ value types in chunks and clears the unused values on setPos() usage. |
135 | | -template <typename T, int chunkEntries> class PythonQtValueStorageWithCleanup : public PythonQtValueStorage<T, chunkEntries> |
136 | | -{ |
137 | | -public: |
138 | | - void setPos(const PythonQtValueStoragePosition& pos) { |
139 | | - if (_chunkIdx > pos.chunkIdx) { |
140 | | - T* firstChunk = _chunks.at(pos.chunkIdx); |
141 | | - // clear region in first chunk |
142 | | - for (int i = pos.chunkOffset; i < chunkEntries; i++) { |
143 | | - firstChunk[i] = T(); |
144 | | - } |
145 | | - for (int chunk = pos.chunkIdx + 1; chunk < _chunkIdx; chunk++) { |
146 | | - // clear the full chunks between the first and last chunk |
147 | | - T* fullChunk = _chunks.at(chunk); |
148 | | - for (int i = 0; i < chunkEntries; i++) { |
149 | | - fullChunk[i] = T(); |
150 | | - } |
151 | | - } |
152 | | - // clear region in last chunk |
153 | | - T* lastChunk = _chunks.at(_chunkIdx); |
154 | | - for (int i = 0; i < _chunkOffset; i++) { |
155 | | - lastChunk[i] = T(); |
156 | | - } |
157 | | - } else if (_chunkIdx == pos.chunkIdx) { |
158 | | - // clear the region in the last chunk only |
159 | | - T* lastChunk = _chunks.at(_chunkIdx); |
160 | | - for (int i = pos.chunkOffset; i<_chunkOffset; i++) { |
161 | | - lastChunk[i] = T(); |
162 | | - } |
163 | | - } |
164 | | - |
165 | | - PythonQtValueStorage<T, chunkEntries>::setPos(pos); |
166 | | - } |
| 89 | + //! Resets the pod and variant argument lists to empty lists. |
| 90 | + void reset(); |
| 91 | + |
| 92 | + //! Get next pointer to a variant |
| 93 | + QVariant* nextVariantPtr(); |
| 94 | + //! Get next pointer to a POD. |
| 95 | + quint64* nextPODPtr(); |
167 | 96 |
|
168 | 97 | private: |
169 | | - using PythonQtValueStorage<T, chunkEntries>::_chunks; |
170 | | - using PythonQtValueStorage<T, chunkEntries>::_chunkIdx; |
171 | | - using PythonQtValueStorage<T, chunkEntries>::_chunkOffset; |
172 | | - using PythonQtValueStorage<T, chunkEntries>::_currentChunk; |
| 98 | + PythonQtArgumentFrame(); |
| 99 | + ~PythonQtArgumentFrame(); |
| 100 | + |
| 101 | + std::vector<quint64> _podArgs; |
| 102 | + std::vector<QVariant> _variantArgs; |
| 103 | + |
| 104 | + PythonQtArgumentFrame* _freeListNext; |
| 105 | + |
| 106 | + static PythonQtArgumentFrame* _freeListHead; |
173 | 107 | }; |
174 | 108 |
|
175 | 109 | #endif |
0 commit comments