PyCyBase 0.1.8.post4__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. cbase/__infra__.pxd +6 -0
  2. cbase/__init__.pxd +6 -0
  3. cbase/__init__.py +28 -0
  4. cbase/allocator_protocol/__infra__.pxd +58 -0
  5. cbase/allocator_protocol/__init__.pxd +58 -0
  6. cbase/allocator_protocol/__init__.py +45 -0
  7. cbase/allocator_protocol/c_allocator_protocol.c +31818 -0
  8. cbase/allocator_protocol/c_allocator_protocol.cp313-win_amd64.pyd +0 -0
  9. cbase/allocator_protocol/c_allocator_protocol.h +352 -0
  10. cbase/allocator_protocol/c_allocator_protocol.pxd +64 -0
  11. cbase/allocator_protocol/c_allocator_protocol.pyi +144 -0
  12. cbase/allocator_protocol/c_allocator_protocol.pyx +209 -0
  13. cbase/allocator_protocol/c_heap_allocator.c +38144 -0
  14. cbase/allocator_protocol/c_heap_allocator.cp313-win_amd64.pyd +0 -0
  15. cbase/allocator_protocol/c_heap_allocator.h +444 -0
  16. cbase/allocator_protocol/c_heap_allocator.pxd +97 -0
  17. cbase/allocator_protocol/c_heap_allocator.pyi +161 -0
  18. cbase/allocator_protocol/c_heap_allocator.pyx +300 -0
  19. cbase/allocator_protocol/c_nt_shm_allocator.c +33399 -0
  20. cbase/allocator_protocol/c_nt_shm_allocator.cp313-win_amd64.pyd +0 -0
  21. cbase/allocator_protocol/c_nt_shm_allocator.h +996 -0
  22. cbase/allocator_protocol/c_nt_shm_allocator.pxd +102 -0
  23. cbase/allocator_protocol/c_nt_shm_allocator.pyx +223 -0
  24. cbase/allocator_protocol/c_shm_allocator.h +1168 -0
  25. cbase/allocator_protocol/c_shm_allocator.pxd +142 -0
  26. cbase/allocator_protocol/c_shm_allocator.pyi +299 -0
  27. cbase/allocator_protocol/c_shm_allocator.pyx +442 -0
  28. cbase/allocator_protocol/c_shm_comp.c +4643 -0
  29. cbase/allocator_protocol/c_shm_comp.cp313-win_amd64.pyd +0 -0
  30. cbase/allocator_protocol/c_shm_comp.h +49 -0
  31. cbase/allocator_protocol/c_shm_comp.pxd +38 -0
  32. cbase/allocator_protocol/c_shm_comp.pyx +1 -0
  33. cbase/backports/__infra__.pxd +17 -0
  34. cbase/backports/__init__.pxd +17 -0
  35. cbase/backports/__init__.py +9 -0
  36. cbase/backports/pydict.h +55 -0
  37. cbase/backports/pydict.pxd +5 -0
  38. cbase/backports/pylong.c +9946 -0
  39. cbase/backports/pylong.cp313-win_amd64.pyd +0 -0
  40. cbase/backports/pylong.h +79 -0
  41. cbase/backports/pylong.pxd +23 -0
  42. cbase/backports/pylong.pyx +61 -0
  43. cbase/bytemap/__infra__.pxd +42 -0
  44. cbase/bytemap/__init__.pxd +42 -0
  45. cbase/bytemap/__init__.py +21 -0
  46. cbase/bytemap/c_bytemap.c +52076 -0
  47. cbase/bytemap/c_bytemap.cp313-win_amd64.pyd +0 -0
  48. cbase/bytemap/c_bytemap.h +867 -0
  49. cbase/bytemap/c_bytemap.pxd +370 -0
  50. cbase/bytemap/c_bytemap.pyx +1758 -0
  51. cbase/bytemap/xxh3.h +55 -0
  52. cbase/bytemap/xxhash.c +42 -0
  53. cbase/bytemap/xxhash.h +7487 -0
  54. cbase/env.c +11109 -0
  55. cbase/env.cp313-win_amd64.pyd +0 -0
  56. cbase/env.pxd +8 -0
  57. cbase/env.pyi +48 -0
  58. cbase/env.pyx +46 -0
  59. cbase/includes/cbase/allocator_protocol/c_allocator_protocol.c +31818 -0
  60. cbase/includes/cbase/allocator_protocol/c_allocator_protocol.h +352 -0
  61. cbase/includes/cbase/allocator_protocol/c_heap_allocator.c +38144 -0
  62. cbase/includes/cbase/allocator_protocol/c_heap_allocator.h +444 -0
  63. cbase/includes/cbase/allocator_protocol/c_nt_shm_allocator.c +33399 -0
  64. cbase/includes/cbase/allocator_protocol/c_nt_shm_allocator.h +996 -0
  65. cbase/includes/cbase/allocator_protocol/c_shm_allocator.h +1168 -0
  66. cbase/includes/cbase/allocator_protocol/c_shm_comp.c +4643 -0
  67. cbase/includes/cbase/allocator_protocol/c_shm_comp.h +49 -0
  68. cbase/includes/cbase/backports/pydict.h +55 -0
  69. cbase/includes/cbase/backports/pylong.c +9946 -0
  70. cbase/includes/cbase/backports/pylong.h +79 -0
  71. cbase/includes/cbase/bytemap/c_bytemap.c +52076 -0
  72. cbase/includes/cbase/bytemap/c_bytemap.h +867 -0
  73. cbase/includes/cbase/bytemap/xxh3.h +55 -0
  74. cbase/includes/cbase/bytemap/xxhash.c +42 -0
  75. cbase/includes/cbase/bytemap/xxhash.h +7487 -0
  76. cbase/includes/cbase/env.c +11109 -0
  77. cbase/includes/cbase/int128.h +81 -0
  78. cbase/includes/cbase/intern_string/c_intern_string.c +28081 -0
  79. cbase/includes/cbase/intern_string/c_intern_string.h +614 -0
  80. cbase/includes/cbase/nt/pthread_nt_compat.h +102 -0
  81. cbase/includes/cbase/nt/regex_nt_compat.h +133 -0
  82. cbase/includes/cbase/nt/time_sched_nt_compat.h +32 -0
  83. cbase/int128.h +81 -0
  84. cbase/int128.pxd +15 -0
  85. cbase/intern_string/BENCHMARK.md +157 -0
  86. cbase/intern_string/__infra__.pxd +11 -0
  87. cbase/intern_string/__init__.pxd +11 -0
  88. cbase/intern_string/__init__.py +19 -0
  89. cbase/intern_string/c_intern_string.c +28081 -0
  90. cbase/intern_string/c_intern_string.cp313-win_amd64.pyd +0 -0
  91. cbase/intern_string/c_intern_string.h +614 -0
  92. cbase/intern_string/c_intern_string.pxd +118 -0
  93. cbase/intern_string/c_intern_string.pyi +376 -0
  94. cbase/intern_string/c_intern_string.pyx +765 -0
  95. cbase/nt/pthread_nt_compat.h +102 -0
  96. cbase/nt/regex_nt_compat.h +133 -0
  97. cbase/nt/time_sched_nt_compat.h +32 -0
  98. pycybase-0.1.8.post4.dist-info/METADATA +180 -0
  99. pycybase-0.1.8.post4.dist-info/RECORD +101 -0
  100. pycybase-0.1.8.post4.dist-info/WHEEL +5 -0
  101. pycybase-0.1.8.post4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,444 @@
1
+ #ifndef AP_HEAP_C_HEAP_ALLOCATOR_H
2
+ #define AP_HEAP_C_HEAP_ALLOCATOR_H
3
+
4
+ #include <errno.h>
5
+ #include <stddef.h>
6
+ #include <stdint.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ #ifdef _WIN32
11
+ #include "cbase/nt/pthread_nt_compat.h"
12
+ #else
13
+ #include <pthread.h>
14
+ #endif
15
+
16
+ // ========== Configuration ==========
17
+
18
+ #ifndef AP_HEAP_AUTOPAGE_CAPACITY
19
+ #define AP_HEAP_AUTOPAGE_CAPACITY (64 * 1024) /* 64 KiB */
20
+ #endif
21
+
22
+ #ifndef AP_HEAP_AUTOPAGE_CAPACITY_MAX
23
+ #define AP_HEAP_AUTOPAGE_CAPACITY_MAX (16 * 1024 * 1024) /* 16 MiB */
24
+ #endif
25
+
26
+ #ifndef AP_HEAP_AUTOPAGE_ALIGNMENT
27
+ #define AP_HEAP_AUTOPAGE_ALIGNMENT (4 * 1024) /* 4 KiB */
28
+ #endif
29
+
30
+ // ========== Heap Allocator Structs ==========
31
+
32
+ typedef struct heap_memory_block {
33
+ size_t capacity;
34
+ size_t size;
35
+ struct heap_memory_block* next_free;
36
+ struct heap_memory_block* next_allocated;
37
+ struct heap_page* parent_page;
38
+ char buffer[];
39
+ } heap_memory_block;
40
+
41
+ typedef struct heap_page {
42
+ size_t capacity;
43
+ size_t occupied;
44
+ struct heap_allocator* allocator;
45
+ struct heap_page* prev;
46
+ struct heap_memory_block* allocated;
47
+ char buffer[];
48
+ } heap_page;
49
+
50
+ typedef struct heap_allocator {
51
+ pthread_mutex_t lock;
52
+ size_t mapped_pages;
53
+ struct heap_memory_block* free_list;
54
+ struct heap_page* active_page;
55
+ size_t autopage_capacity;
56
+ size_t autopage_capacity_max;
57
+ size_t autopage_alignment;
58
+ } heap_allocator;
59
+
60
+ // ========== Utility Functions ==========
61
+
62
+ static inline size_t c_heap_page_roundup(heap_allocator* allocator, size_t size) {
63
+ return (size + allocator->autopage_alignment - 1) & ~(allocator->autopage_alignment - 1);
64
+ }
65
+
66
+ static inline size_t c_heap_block_roundup(size_t size) {
67
+ return (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
68
+ }
69
+
70
+ static inline void c_heap_page_reclaim(heap_allocator* allocator, heap_page* page) {
71
+ if (!allocator || !page) {
72
+ errno = EINVAL;
73
+ return;
74
+ }
75
+
76
+ heap_memory_block** prevp = &page->allocated;
77
+ while (*prevp) {
78
+ heap_memory_block* block = *prevp;
79
+ if (block->size != 0) {
80
+ break;
81
+ }
82
+
83
+ *prevp = block->next_allocated;
84
+ block->next_allocated = NULL;
85
+
86
+ heap_memory_block** free_prev = &allocator->free_list;
87
+ while (*free_prev && *free_prev != block) {
88
+ free_prev = &(*free_prev)->next_free;
89
+ }
90
+ if (*free_prev == block) {
91
+ *free_prev = block->next_free;
92
+ }
93
+ block->next_free = NULL;
94
+
95
+ size_t cap_total = block->capacity + sizeof(heap_memory_block);
96
+ if (page->occupied >= cap_total) {
97
+ page->occupied -= cap_total;
98
+ }
99
+ }
100
+ }
101
+
102
+ // ========== Public API Functions ==========
103
+
104
+ static inline heap_page* c_heap_allocator_extend(heap_allocator* allocator, size_t capacity, pthread_mutex_t* lock) {
105
+ if (!allocator) {
106
+ errno = EINVAL;
107
+ return NULL;
108
+ }
109
+
110
+ uint8_t locked = 0;
111
+
112
+ if (lock) {
113
+ int ret = pthread_mutex_lock(lock);
114
+ if (ret != 0) {
115
+ errno = ret;
116
+ return NULL;
117
+ }
118
+ locked = 1;
119
+ }
120
+
121
+ if (capacity == 0) {
122
+ if (!allocator->active_page) {
123
+ capacity = allocator->autopage_capacity;
124
+ }
125
+ else {
126
+ size_t prev_cap = allocator->active_page->capacity;
127
+ capacity = prev_cap * 2;
128
+ if (capacity < allocator->autopage_capacity) {
129
+ capacity = allocator->autopage_capacity;
130
+ }
131
+ else if (capacity > allocator->autopage_capacity_max) {
132
+ capacity = allocator->autopage_capacity_max;
133
+ }
134
+ }
135
+ }
136
+
137
+ size_t total_capacity = c_heap_page_roundup(allocator, capacity);
138
+
139
+ heap_page* page = (heap_page*) calloc(1, total_capacity);
140
+
141
+ if (!page) {
142
+ if (locked) pthread_mutex_unlock(lock);
143
+ return NULL;
144
+ }
145
+
146
+ page->capacity = total_capacity;
147
+ page->occupied = sizeof(heap_page);
148
+ page->allocator = allocator;
149
+ page->allocated = NULL;
150
+ page->prev = allocator->active_page;
151
+ allocator->active_page = page;
152
+ allocator->mapped_pages++;
153
+
154
+ if (locked) pthread_mutex_unlock(lock);
155
+ return page;
156
+ }
157
+
158
+ static inline heap_allocator* c_heap_allocator_new() {
159
+ heap_allocator* allocator = (heap_allocator*) calloc(1, sizeof(heap_allocator));
160
+ if (!allocator) {
161
+ return NULL;
162
+ }
163
+
164
+ if (pthread_mutex_init(&allocator->lock, NULL) != 0) {
165
+ free(allocator);
166
+ return NULL;
167
+ }
168
+
169
+ allocator->mapped_pages = 0;
170
+ allocator->free_list = NULL;
171
+ allocator->active_page = NULL;
172
+ allocator->autopage_capacity = AP_HEAP_AUTOPAGE_CAPACITY;
173
+ allocator->autopage_capacity_max = AP_HEAP_AUTOPAGE_CAPACITY_MAX;
174
+ allocator->autopage_alignment = AP_HEAP_AUTOPAGE_ALIGNMENT;
175
+
176
+ return allocator;
177
+ }
178
+
179
+ static inline void c_heap_allocator_free(heap_allocator* allocator) {
180
+ if (!allocator) {
181
+ return;
182
+ }
183
+
184
+ heap_page* page = allocator->active_page;
185
+ while (page) {
186
+ heap_page* prev = page->prev;
187
+ free(page);
188
+ page = prev;
189
+ }
190
+
191
+ pthread_mutex_destroy(&allocator->lock);
192
+ free(allocator);
193
+ }
194
+
195
+ static inline void* c_heap_calloc(heap_allocator* allocator, size_t size, pthread_mutex_t* lock) {
196
+ if (!allocator || size == 0) {
197
+ errno = EINVAL;
198
+ return NULL;
199
+ }
200
+
201
+ size_t cap_net = c_heap_block_roundup(size);
202
+ size_t overhead = sizeof(heap_memory_block);
203
+ size_t cap_total = cap_net + overhead;
204
+
205
+ uint8_t locked = 0;
206
+ pthread_mutex_t* builtin_lock = &allocator->lock;
207
+ pthread_mutex_t* child_lock = &allocator->lock;
208
+ if (lock) {
209
+ if (lock == builtin_lock) {
210
+ child_lock = NULL;
211
+ }
212
+ int ret = pthread_mutex_lock(lock);
213
+ if (ret != 0) {
214
+ errno = ret;
215
+ return NULL;
216
+ }
217
+ locked = 1;
218
+ }
219
+ else {
220
+ child_lock = NULL;
221
+ }
222
+
223
+ heap_page* page = allocator->active_page;
224
+ if (!page) {
225
+ size_t target_cap = allocator->autopage_capacity;
226
+ while (target_cap < cap_total + sizeof(heap_page)) {
227
+ target_cap *= 2;
228
+ }
229
+
230
+ page = c_heap_allocator_extend(allocator, target_cap, child_lock);
231
+ if (!page) {
232
+ if (locked) pthread_mutex_unlock(lock);
233
+ return NULL;
234
+ }
235
+ }
236
+
237
+ if (page->occupied + cap_total > page->capacity) {
238
+ size_t target_cap = page->capacity;
239
+
240
+ if (target_cap < allocator->autopage_capacity) {
241
+ target_cap = allocator->autopage_capacity;
242
+ }
243
+ else if (target_cap < allocator->autopage_capacity_max) {
244
+ target_cap *= 2;
245
+ }
246
+
247
+ while (target_cap < cap_total + sizeof(heap_page)) {
248
+ target_cap *= 2;
249
+ }
250
+ page = c_heap_allocator_extend(allocator, target_cap, child_lock);
251
+ if (!page) {
252
+ if (locked) pthread_mutex_unlock(lock);
253
+ return NULL;
254
+ }
255
+ }
256
+
257
+ size_t offset = page->occupied;
258
+ heap_memory_block* block = (heap_memory_block*) ((char*) page + offset);
259
+ block->capacity = cap_net;
260
+ block->size = size;
261
+ block->next_free = NULL;
262
+
263
+ block->parent_page = page;
264
+ block->next_allocated = page->allocated;
265
+ page->allocated = block;
266
+ page->occupied += cap_total;
267
+
268
+ if (locked) pthread_mutex_unlock(lock);
269
+
270
+ memset(block + 1, 0, cap_net);
271
+ return (void*) block->buffer;
272
+ }
273
+
274
+ static inline void* c_heap_request(heap_allocator* allocator, size_t size, int scan_all_pages, pthread_mutex_t* lock) {
275
+ if (!allocator || size == 0) {
276
+ errno = EINVAL;
277
+ return NULL;
278
+ }
279
+
280
+ size_t cap_net = c_heap_block_roundup(size);
281
+ size_t overhead = sizeof(heap_memory_block);
282
+ size_t cap_total = cap_net + overhead;
283
+
284
+ uint8_t locked = 0;
285
+ pthread_mutex_t* builtin_lock = &allocator->lock;
286
+ pthread_mutex_t* child_lock = &allocator->lock;
287
+ if (lock) {
288
+ if (lock == builtin_lock) {
289
+ child_lock = NULL;
290
+ }
291
+ int ret = pthread_mutex_lock(lock);
292
+ if (ret != 0) {
293
+ errno = ret;
294
+ return NULL;
295
+ }
296
+ locked = 1;
297
+ }
298
+ else {
299
+ child_lock = NULL;
300
+ }
301
+
302
+ heap_memory_block** prevp = &allocator->free_list;
303
+ heap_memory_block* free_blk = allocator->free_list;
304
+ while (free_blk) {
305
+ if (free_blk->capacity >= cap_net) {
306
+ *prevp = free_blk->next_free;
307
+ free_blk->next_free = NULL;
308
+ free_blk->size = size;
309
+ if (locked) pthread_mutex_unlock(lock);
310
+ memset(free_blk + 1, 0, cap_net);
311
+ return (void*) free_blk->buffer;
312
+ }
313
+ prevp = &free_blk->next_free;
314
+ free_blk = free_blk->next_free;
315
+ }
316
+
317
+ heap_page* target_page = NULL;
318
+ if (scan_all_pages) {
319
+ heap_page* iter = allocator->active_page;
320
+ while (iter) {
321
+ if (iter->occupied + cap_total <= iter->capacity) {
322
+ target_page = iter;
323
+ break;
324
+ }
325
+ iter = iter->prev;
326
+ }
327
+ }
328
+ else if (allocator->active_page) {
329
+ heap_page* meta = allocator->active_page;
330
+ if (meta && meta->occupied + cap_total <= meta->capacity) {
331
+ target_page = allocator->active_page;
332
+ }
333
+ }
334
+
335
+ if (!target_page) {
336
+ heap_page* current = allocator->active_page;
337
+ size_t target_cap;
338
+
339
+ if (!current) {
340
+ target_cap = allocator->autopage_capacity;
341
+ while (target_cap < cap_total + sizeof(heap_page)) {
342
+ target_cap *= 2;
343
+ }
344
+ }
345
+ else {
346
+ size_t prev_cap = current->capacity;
347
+ size_t new_cap = prev_cap;
348
+
349
+ if (new_cap < allocator->autopage_capacity) {
350
+ new_cap = allocator->autopage_capacity;
351
+ }
352
+ else if (new_cap < allocator->autopage_capacity_max) {
353
+ new_cap *= 2;
354
+ }
355
+
356
+ while (new_cap < cap_total + sizeof(heap_page)) {
357
+ new_cap *= 2;
358
+ }
359
+ target_cap = new_cap;
360
+ }
361
+
362
+ target_page = c_heap_allocator_extend(allocator, target_cap, child_lock);
363
+ if (!target_page) {
364
+ if (locked) pthread_mutex_unlock(lock);
365
+ return NULL;
366
+ }
367
+ }
368
+
369
+ size_t offset = target_page->occupied;
370
+ heap_memory_block* block = (heap_memory_block*) ((char*) target_page + offset);
371
+ block->capacity = cap_net;
372
+ block->size = size;
373
+ block->next_free = NULL;
374
+
375
+ block->parent_page = target_page;
376
+ block->next_allocated = target_page->allocated;
377
+ target_page->allocated = block;
378
+
379
+ target_page->occupied += cap_total;
380
+
381
+ if (locked) pthread_mutex_unlock(lock);
382
+
383
+ memset(block + 1, 0, cap_net);
384
+ return (void*) block->buffer;
385
+ }
386
+
387
+ static inline void c_heap_free(void* ptr, pthread_mutex_t* lock) {
388
+ if (!ptr) {
389
+ errno = EINVAL;
390
+ return;
391
+ }
392
+
393
+ heap_memory_block* block = (heap_memory_block*) ((char*) ptr - sizeof(heap_memory_block));
394
+ heap_page* page = block->parent_page;
395
+ if (!page || !page->allocator) {
396
+ errno = EINVAL;
397
+ return;
398
+ }
399
+
400
+ heap_allocator* allocator = page->allocator;
401
+
402
+ uint8_t locked = 0;
403
+ if (lock) {
404
+ int ret = pthread_mutex_lock(lock);
405
+ if (ret != 0) {
406
+ errno = ret;
407
+ return;
408
+ }
409
+ locked = 1;
410
+ }
411
+
412
+ block->size = 0;
413
+ block->next_free = allocator->free_list;
414
+ allocator->free_list = block;
415
+
416
+ if (locked) pthread_mutex_unlock(lock);
417
+ }
418
+
419
+ static inline void c_heap_reclaim(heap_allocator* allocator, pthread_mutex_t* lock) {
420
+ if (!allocator) {
421
+ errno = EINVAL;
422
+ return;
423
+ }
424
+
425
+ uint8_t locked = 0;
426
+ if (lock) {
427
+ int ret = pthread_mutex_lock(lock);
428
+ if (ret != 0) {
429
+ errno = ret;
430
+ return;
431
+ }
432
+ locked = 1;
433
+ }
434
+
435
+ heap_page* page = allocator->active_page;
436
+ while (page) {
437
+ c_heap_page_reclaim(allocator, page);
438
+ page = page->prev;
439
+ }
440
+
441
+ if (locked) pthread_mutex_unlock(lock);
442
+ }
443
+
444
+ #endif /* AP_HEAP_C_HEAP_ALLOCATOR_H */
@@ -0,0 +1,97 @@
1
+
2
+ cdef extern from "cbase/allocator_protocol/c_heap_allocator.h":
3
+ const size_t AP_HEAP_AUTOPAGE_CAPACITY
4
+ const size_t AP_HEAP_AUTOPAGE_CAPACITY_MAX
5
+ const size_t AP_HEAP_AUTOPAGE_ALIGNMENT
6
+
7
+ ctypedef struct pthread_mutex_t:
8
+ pass
9
+
10
+ ctypedef struct heap_memory_block:
11
+ size_t capacity
12
+ size_t size
13
+ heap_memory_block* next_free
14
+ heap_memory_block* next_allocated
15
+ heap_page* parent_page
16
+ char buffer[]
17
+
18
+ ctypedef struct heap_page:
19
+ size_t capacity
20
+ size_t occupied
21
+ heap_allocator* allocator
22
+ heap_page* prev
23
+ heap_memory_block* allocated
24
+ char buffer[]
25
+
26
+ ctypedef struct heap_allocator:
27
+ pthread_mutex_t lock
28
+ size_t mapped_pages
29
+ heap_memory_block* free_list
30
+ heap_page* active_page
31
+ size_t autopage_capacity
32
+ size_t autopage_capacity_max
33
+ size_t autopage_alignment
34
+
35
+ int pthread_mutex_init(pthread_mutex_t* mutex, void* attr) noexcept nogil
36
+ int pthread_mutex_lock(pthread_mutex_t* mutex) noexcept nogil
37
+ int pthread_mutex_unlock(pthread_mutex_t* mutex) noexcept nogil
38
+ int pthread_mutex_destroy(pthread_mutex_t* mutex) noexcept nogil
39
+
40
+ size_t c_heap_page_roundup(heap_allocator* allocator, size_t size) noexcept nogil
41
+ size_t c_heap_block_roundup(size_t size) noexcept nogil
42
+ void c_heap_page_reclaim(heap_allocator* allocator, heap_page* page) noexcept nogil
43
+
44
+ heap_page* c_heap_allocator_extend(heap_allocator* allocator, size_t capacity, pthread_mutex_t* lock) noexcept nogil
45
+ heap_allocator* c_heap_allocator_new() noexcept nogil
46
+ void c_heap_allocator_free(heap_allocator* allocator) noexcept nogil
47
+ void* c_heap_calloc(heap_allocator* allocator, size_t size, pthread_mutex_t* lock) noexcept nogil
48
+ void* c_heap_request(heap_allocator* allocator, size_t size, int scan_all_pages, pthread_mutex_t* lock) noexcept nogil
49
+ void c_heap_free(void* ptr, pthread_mutex_t* lock) noexcept nogil
50
+ void c_heap_reclaim(heap_allocator* allocator, pthread_mutex_t* lock) noexcept nogil
51
+
52
+
53
+ cdef class HeapMemoryPage:
54
+ cdef heap_page* page
55
+
56
+ @staticmethod
57
+ cdef inline HeapMemoryPage c_from_header(heap_page* header)
58
+
59
+ cpdef void reclaim(self)
60
+
61
+
62
+ cdef class HeapMemoryBlock:
63
+ cdef heap_memory_block* block
64
+ cdef readonly bint owner
65
+
66
+ @staticmethod
67
+ cdef inline HeapMemoryBlock c_from_header(heap_memory_block* header, bint owner=?)
68
+
69
+
70
+ cdef class HeapAllocator:
71
+ cdef heap_allocator* allocator
72
+ cdef readonly bint owner
73
+
74
+ @staticmethod
75
+ cdef HeapAllocator c_from_header(heap_allocator* header, bint owner=?)
76
+
77
+ cdef inline heap_page* c_extend(self, size_t capacity=?, pthread_mutex_t* lock=?)
78
+
79
+ cdef inline void* c_calloc(self, size_t size, pthread_mutex_t* lock=?)
80
+
81
+ cdef inline void* c_request(self, size_t size, int scan_all_pages=?, pthread_mutex_t* lock=?)
82
+
83
+ cdef inline void c_free(self, void* ptr, pthread_mutex_t* lock=?)
84
+
85
+ cpdef HeapMemoryPage extend(self, size_t capacity=?, bint with_lock=?)
86
+
87
+ cpdef HeapMemoryBlock calloc(self, size_t size, bint with_lock=?)
88
+
89
+ cpdef HeapMemoryBlock request(self, size_t size, bint with_lock=?, bint scan_all_pages=?)
90
+
91
+ cpdef void free(self, HeapMemoryBlock buffer, bint with_lock=?)
92
+
93
+ cpdef void reclaim(self, bint with_lock=?)
94
+
95
+
96
+ cdef HeapAllocator ALLOCATOR
97
+ cdef heap_allocator* C_ALLOCATOR
@@ -0,0 +1,161 @@
1
+ import ctypes
2
+ from collections.abc import Generator
3
+ from dataclasses import dataclass
4
+ from typing import Annotated
5
+
6
+
7
+ @dataclass
8
+ class ValueRange:
9
+ lo: int
10
+ hi: int
11
+
12
+
13
+ UINTPTR_MAX = ctypes.c_void_p(-1).value
14
+ uintptr_t = Annotated[int, ValueRange(0, UINTPTR_MAX), ctypes.c_void_p]
15
+
16
+
17
+ class HeapMemoryBlock:
18
+ """Typed wrapper around an allocator block header."""
19
+
20
+ owner: bool
21
+
22
+ def __init__(self, block: uintptr_t = 0, owner: bool = False) -> None: ...
23
+
24
+ def __repr__(self) -> str: ...
25
+
26
+ @property
27
+ def size(self) -> int:
28
+ """Requested payload size in bytes (-1 if uninitialized)."""
29
+
30
+ @property
31
+ def capacity(self) -> int:
32
+ """Aligned capacity of the block (-1 if uninitialized)."""
33
+
34
+ @property
35
+ def next_free(self) -> HeapMemoryBlock | None:
36
+ """Next entry in the allocator free list, if any."""
37
+
38
+ @property
39
+ def next_allocated(self) -> HeapMemoryBlock | None:
40
+ """Next entry in the owning page's allocation list, if any."""
41
+
42
+ @property
43
+ def parent_page(self) -> HeapMemoryPage | None:
44
+ """Owning page wrapper, or None when detached."""
45
+
46
+ @property
47
+ def buffer(self) -> memoryview:
48
+ """Memoryview of the user buffer."""
49
+
50
+ @property
51
+ def address(self) -> str | None:
52
+ """Hex string of the buffer address."""
53
+
54
+
55
+ class HeapMemoryPage:
56
+ """Represents a single heap-managed page."""
57
+
58
+ def __init__(self, page_addr: uintptr_t = 0) -> None: ...
59
+
60
+ def __repr__(self) -> str: ...
61
+
62
+ @classmethod
63
+ def from_buffer(cls, buffer_addr: uintptr_t) -> HeapMemoryPage:
64
+ """Reconstruct a page wrapper from one of its block buffers."""
65
+
66
+ def allocated(self) -> Generator[HeapMemoryBlock]:
67
+ """Iterate allocated blocks newest-first."""
68
+
69
+ def reclaim(self) -> None:
70
+ """Best-effort reclaim of freed blocks back to unused space."""
71
+
72
+ @property
73
+ def capacity(self) -> int:
74
+ """Total payload capacity of the page in bytes."""
75
+
76
+ @property
77
+ def occupied(self) -> int:
78
+ """Currently occupied bytes on the page."""
79
+
80
+ @property
81
+ def address(self) -> str | None:
82
+ """Hex string of the page buffer address."""
83
+
84
+ @property
85
+ def allocator(self) -> HeapAllocator | None:
86
+ """Owning allocator wrapper, or None."""
87
+
88
+
89
+ class HeapAllocator:
90
+ """Top-level heap allocator."""
91
+
92
+ owner: bool
93
+
94
+ def __init__(self) -> None: ...
95
+
96
+ def __repr__(self) -> str: ...
97
+
98
+ def extend(self, capacity: int = 0, with_lock: bool = True) -> HeapMemoryPage:
99
+ """Add a page (auto-sized when capacity is 0)."""
100
+
101
+ def calloc(self, size: int, with_lock: bool = True) -> HeapMemoryBlock:
102
+ """Allocate zeroed memory from the active page (auto-extending)."""
103
+
104
+ def request(
105
+ self,
106
+ size: int,
107
+ with_lock: bool = True,
108
+ scan_all_pages: bool = True,
109
+ ) -> HeapMemoryBlock:
110
+ """Request a zeroed block, optionally scanning older pages."""
111
+
112
+ def free(self, buffer: HeapMemoryBlock, with_lock: bool = True) -> None:
113
+ """Return a block to the allocator free list."""
114
+
115
+ def reclaim(self, with_lock: bool = True) -> None:
116
+ """Reclaim freed space across all pages."""
117
+
118
+ def pages(self) -> Generator[HeapMemoryPage]:
119
+ """Iterate mapped pages newest-first."""
120
+
121
+ def allocated(self) -> Generator[HeapMemoryBlock]:
122
+ """Iterate allocated blocks across all pages."""
123
+
124
+ def free_list(self) -> Generator[HeapMemoryBlock]:
125
+ """Iterate the allocator-wide free list."""
126
+
127
+ @property
128
+ def mapped_pages(self) -> int:
129
+ """Count of pages currently mapped by the allocator."""
130
+
131
+ @property
132
+ def active_page(self) -> HeapMemoryPage | None:
133
+ """Most recently mapped page, if any."""
134
+
135
+ @property
136
+ def autopage_capacity(self) -> int:
137
+ """Default capacity for auto-sized pages (read/write)."""
138
+
139
+ @autopage_capacity.setter
140
+ def autopage_capacity(self, value: int) -> None: ...
141
+
142
+ @property
143
+ def autopage_capacity_max(self) -> int:
144
+ """Maximum capacity a page can grow to (read/write)."""
145
+
146
+ @autopage_capacity_max.setter
147
+ def autopage_capacity_max(self, value: int) -> None: ...
148
+
149
+ @property
150
+ def autopage_alignment(self) -> int:
151
+ """Page alignment in bytes (read/write)."""
152
+
153
+ @autopage_alignment.setter
154
+ def autopage_alignment(self, value: int) -> None: ...
155
+
156
+
157
+ ALLOCATOR: HeapAllocator
158
+
159
+ DEFAULT_AUTOPAGE_CAPACITY: int
160
+ MAX_AUTOPAGE_CAPACITY: int
161
+ DEFAULT_AUTOPAGE_ALIGNMENT: int