PyCyBase 0.1.10__cp315-cp315-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.
- cbase/__infra__.pxd +6 -0
- cbase/__init__.pxd +6 -0
- cbase/__init__.py +31 -0
- cbase/allocator_protocol/__infra__.pxd +65 -0
- cbase/allocator_protocol/__init__.pxd +65 -0
- cbase/allocator_protocol/__init__.py +45 -0
- cbase/allocator_protocol/c_allocator_protocol.c +31874 -0
- cbase/allocator_protocol/c_allocator_protocol.cp315-win_amd64.pyd +0 -0
- cbase/allocator_protocol/c_allocator_protocol.h +352 -0
- cbase/allocator_protocol/c_allocator_protocol.pxd +66 -0
- cbase/allocator_protocol/c_allocator_protocol.pyi +144 -0
- cbase/allocator_protocol/c_allocator_protocol.pyx +209 -0
- cbase/allocator_protocol/c_heap_allocator.c +38225 -0
- cbase/allocator_protocol/c_heap_allocator.cp315-win_amd64.pyd +0 -0
- cbase/allocator_protocol/c_heap_allocator.h +554 -0
- cbase/allocator_protocol/c_heap_allocator.pxd +105 -0
- cbase/allocator_protocol/c_heap_allocator.pyi +161 -0
- cbase/allocator_protocol/c_heap_allocator.pyx +303 -0
- cbase/allocator_protocol/c_nt_shm_allocator.c +33455 -0
- cbase/allocator_protocol/c_nt_shm_allocator.cp315-win_amd64.pyd +0 -0
- cbase/allocator_protocol/c_nt_shm_allocator.h +1105 -0
- cbase/allocator_protocol/c_nt_shm_allocator.pxd +110 -0
- cbase/allocator_protocol/c_nt_shm_allocator.pyx +223 -0
- cbase/allocator_protocol/c_shm_allocator.h +1270 -0
- cbase/allocator_protocol/c_shm_allocator.pxd +150 -0
- cbase/allocator_protocol/c_shm_allocator.pyi +299 -0
- cbase/allocator_protocol/c_shm_allocator.pyx +445 -0
- cbase/allocator_protocol/c_shm_comp.c +4654 -0
- cbase/allocator_protocol/c_shm_comp.cp315-win_amd64.pyd +0 -0
- cbase/allocator_protocol/c_shm_comp.h +49 -0
- cbase/allocator_protocol/c_shm_comp.pxd +46 -0
- cbase/allocator_protocol/c_shm_comp.pyx +1 -0
- cbase/backports/__infra__.pxd +17 -0
- cbase/backports/__init__.pxd +17 -0
- cbase/backports/__init__.py +9 -0
- cbase/backports/pydict.h +55 -0
- cbase/backports/pydict.pxd +5 -0
- cbase/backports/pylong.c +9965 -0
- cbase/backports/pylong.cp315-win_amd64.pyd +0 -0
- cbase/backports/pylong.h +79 -0
- cbase/backports/pylong.pxd +23 -0
- cbase/backports/pylong.pyx +61 -0
- cbase/bytemap/__infra__.pxd +42 -0
- cbase/bytemap/__init__.pxd +42 -0
- cbase/bytemap/__init__.py +21 -0
- cbase/bytemap/c_bytemap.c +52151 -0
- cbase/bytemap/c_bytemap.cp315-win_amd64.pyd +0 -0
- cbase/bytemap/c_bytemap.h +867 -0
- cbase/bytemap/c_bytemap.pxd +370 -0
- cbase/bytemap/c_bytemap.pyx +1760 -0
- cbase/bytemap/xxh3.h +55 -0
- cbase/bytemap/xxhash.c +42 -0
- cbase/bytemap/xxhash.h +7487 -0
- cbase/config_view.c +7253 -0
- cbase/config_view.cp315-win_amd64.pyd +0 -0
- cbase/config_view.pyx +85 -0
- cbase/env.c +11120 -0
- cbase/env.cp315-win_amd64.pyd +0 -0
- cbase/env.pxd +8 -0
- cbase/env.pyi +48 -0
- cbase/env.pyx +46 -0
- cbase/includes/cbase/allocator_protocol/c_allocator_protocol.c +31874 -0
- cbase/includes/cbase/allocator_protocol/c_allocator_protocol.h +352 -0
- cbase/includes/cbase/allocator_protocol/c_heap_allocator.c +38225 -0
- cbase/includes/cbase/allocator_protocol/c_heap_allocator.h +554 -0
- cbase/includes/cbase/allocator_protocol/c_nt_shm_allocator.c +33455 -0
- cbase/includes/cbase/allocator_protocol/c_nt_shm_allocator.h +1105 -0
- cbase/includes/cbase/allocator_protocol/c_shm_allocator.h +1270 -0
- cbase/includes/cbase/allocator_protocol/c_shm_comp.c +4654 -0
- cbase/includes/cbase/allocator_protocol/c_shm_comp.h +49 -0
- cbase/includes/cbase/backports/pydict.h +55 -0
- cbase/includes/cbase/backports/pylong.c +9965 -0
- cbase/includes/cbase/backports/pylong.h +79 -0
- cbase/includes/cbase/bytemap/c_bytemap.c +52151 -0
- cbase/includes/cbase/bytemap/c_bytemap.h +867 -0
- cbase/includes/cbase/bytemap/xxh3.h +55 -0
- cbase/includes/cbase/bytemap/xxhash.c +42 -0
- cbase/includes/cbase/bytemap/xxhash.h +7487 -0
- cbase/includes/cbase/config_view.c +7253 -0
- cbase/includes/cbase/env.c +11120 -0
- cbase/includes/cbase/int128.h +81 -0
- cbase/includes/cbase/intern_string/c_intern_string.c +28138 -0
- cbase/includes/cbase/intern_string/c_intern_string.h +614 -0
- cbase/includes/cbase/nt/pthread_nt_compat.h +102 -0
- cbase/includes/cbase/nt/regex_nt_compat.h +133 -0
- cbase/includes/cbase/nt/time_sched_nt_compat.h +32 -0
- cbase/int128.h +81 -0
- cbase/int128.pxd +15 -0
- cbase/intern_string/BENCHMARK.md +157 -0
- cbase/intern_string/__infra__.pxd +13 -0
- cbase/intern_string/__init__.pxd +13 -0
- cbase/intern_string/__init__.py +19 -0
- cbase/intern_string/c_intern_string.c +28138 -0
- cbase/intern_string/c_intern_string.cp315-win_amd64.pyd +0 -0
- cbase/intern_string/c_intern_string.h +614 -0
- cbase/intern_string/c_intern_string.pxd +121 -0
- cbase/intern_string/c_intern_string.pyi +376 -0
- cbase/intern_string/c_intern_string.pyx +765 -0
- cbase/nt/pthread_nt_compat.h +102 -0
- cbase/nt/regex_nt_compat.h +133 -0
- cbase/nt/time_sched_nt_compat.h +32 -0
- pycybase-0.1.10.dist-info/METADATA +190 -0
- pycybase-0.1.10.dist-info/RECORD +105 -0
- pycybase-0.1.10.dist-info/WHEEL +5 -0
- pycybase-0.1.10.dist-info/top_level.txt +1 -0
|
@@ -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
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
from libc.errno cimport errno
|
|
2
|
+
from libc.stdint cimport uintptr_t
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
cdef class HeapMemoryPage:
|
|
6
|
+
def __cinit__(self, uintptr_t page_addr=0):
|
|
7
|
+
self.page = <heap_page*> page_addr if page_addr else NULL
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
cdef inline HeapMemoryPage c_from_header(heap_page* header):
|
|
11
|
+
cdef HeapMemoryPage instance = HeapMemoryPage.__new__(HeapMemoryPage, 0)
|
|
12
|
+
instance.page = header
|
|
13
|
+
return instance
|
|
14
|
+
|
|
15
|
+
def __repr__(self):
|
|
16
|
+
if self.page:
|
|
17
|
+
return f"<{self.__class__.__name__}>(capacity={self.capacity:,}, occupied={self.occupied:,})"
|
|
18
|
+
return f"<{self.__class__.__name__}>(uninitialized)"
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_buffer(cls, uintptr_t buffer_addr) -> HeapMemoryPage:
|
|
22
|
+
cdef HeapMemoryPage instance = cls.__new__(cls, 0)
|
|
23
|
+
instance.page = <heap_page*> (<char*> buffer_addr - sizeof(heap_page))
|
|
24
|
+
return instance
|
|
25
|
+
|
|
26
|
+
def allocated(self):
|
|
27
|
+
if not self.page:
|
|
28
|
+
return
|
|
29
|
+
cdef heap_memory_block* block = self.page.allocated
|
|
30
|
+
while block:
|
|
31
|
+
yield HeapMemoryBlock.c_from_header(block, False)
|
|
32
|
+
block = block.next_allocated
|
|
33
|
+
|
|
34
|
+
cpdef void reclaim(self):
|
|
35
|
+
if not self.page:
|
|
36
|
+
raise RuntimeError(f"Uninitialized <{self.__class__.__name__}>")
|
|
37
|
+
c_heap_page_reclaim(self.page.allocator, self.page)
|
|
38
|
+
|
|
39
|
+
property capacity:
|
|
40
|
+
def __get__(self):
|
|
41
|
+
if self.page:
|
|
42
|
+
return <size_t> self.page.capacity
|
|
43
|
+
return 0
|
|
44
|
+
|
|
45
|
+
property occupied:
|
|
46
|
+
def __get__(self):
|
|
47
|
+
if self.page:
|
|
48
|
+
return <size_t> self.page.occupied
|
|
49
|
+
return 0
|
|
50
|
+
|
|
51
|
+
property allocator:
|
|
52
|
+
def __get__(self):
|
|
53
|
+
if not self.page:
|
|
54
|
+
return None
|
|
55
|
+
return HeapAllocator.c_from_header(self.page.allocator, False)
|
|
56
|
+
|
|
57
|
+
property address:
|
|
58
|
+
def __get__(self):
|
|
59
|
+
if not self.page:
|
|
60
|
+
return None
|
|
61
|
+
return f"{<uintptr_t> self.page.buffer:#0x}"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
cdef class HeapMemoryBlock:
|
|
65
|
+
def __cinit__(self, uintptr_t block=0, bint owner=False):
|
|
66
|
+
self.block = <heap_memory_block*> block if block else NULL
|
|
67
|
+
self.owner = owner
|
|
68
|
+
|
|
69
|
+
def __dealloc__(self):
|
|
70
|
+
if not self.owner:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
if self.block:
|
|
74
|
+
c_heap_free(self.block.buffer, &self.block.parent_page.allocator.lock)
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
cdef inline HeapMemoryBlock c_from_header(heap_memory_block* header, bint owner=False):
|
|
78
|
+
cdef HeapMemoryBlock instance = HeapMemoryBlock.__new__(HeapMemoryBlock, 0, owner)
|
|
79
|
+
instance.block = header
|
|
80
|
+
return instance
|
|
81
|
+
|
|
82
|
+
def __repr__(self):
|
|
83
|
+
if self.block:
|
|
84
|
+
return f"<{self.__class__.__name__}>(size={self.block.size}, capacity={self.block.capacity})"
|
|
85
|
+
return f"<{self.__class__.__name__}>(uninitialized)"
|
|
86
|
+
|
|
87
|
+
property size:
|
|
88
|
+
def __get__(self):
|
|
89
|
+
if not self.block:
|
|
90
|
+
return -1
|
|
91
|
+
return <size_t> self.block.size
|
|
92
|
+
|
|
93
|
+
property capacity:
|
|
94
|
+
def __get__(self):
|
|
95
|
+
if not self.block:
|
|
96
|
+
return -1
|
|
97
|
+
return <size_t> self.block.capacity
|
|
98
|
+
|
|
99
|
+
property next_free:
|
|
100
|
+
def __get__(self):
|
|
101
|
+
if self.block and self.block.next_free:
|
|
102
|
+
return HeapMemoryBlock.c_from_header(self.block.next_free, False)
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
property next_allocated:
|
|
106
|
+
def __get__(self):
|
|
107
|
+
if self.block and self.block.next_allocated:
|
|
108
|
+
return HeapMemoryBlock.c_from_header(self.block.next_allocated, False)
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
property parent_page:
|
|
112
|
+
def __get__(self):
|
|
113
|
+
if not self.block:
|
|
114
|
+
return None
|
|
115
|
+
return HeapMemoryPage.c_from_header(self.block.parent_page)
|
|
116
|
+
|
|
117
|
+
property buffer:
|
|
118
|
+
def __get__(self):
|
|
119
|
+
if not self.block:
|
|
120
|
+
return None
|
|
121
|
+
cdef size_t size = self.block.size
|
|
122
|
+
return <char[:size]> self.block.buffer
|
|
123
|
+
|
|
124
|
+
property address:
|
|
125
|
+
def __get__(self):
|
|
126
|
+
if not self.block:
|
|
127
|
+
return None
|
|
128
|
+
return f"{<uintptr_t> self.block.buffer:#0x}"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
cdef class HeapAllocator:
|
|
132
|
+
def __init__(self):
|
|
133
|
+
self.allocator = c_heap_allocator_new()
|
|
134
|
+
if not self.allocator:
|
|
135
|
+
raise OSError(errno, "Initialize heap allocator failed")
|
|
136
|
+
self.owner = True
|
|
137
|
+
|
|
138
|
+
def __dealloc__(self):
|
|
139
|
+
if not self.owner:
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
if self.allocator:
|
|
143
|
+
c_heap_allocator_free(self.allocator)
|
|
144
|
+
|
|
145
|
+
@staticmethod
|
|
146
|
+
cdef HeapAllocator c_from_header(heap_allocator* header, bint owner=False):
|
|
147
|
+
cdef HeapAllocator instance = HeapAllocator.__new__(HeapAllocator)
|
|
148
|
+
instance.allocator = header
|
|
149
|
+
instance.owner = owner
|
|
150
|
+
return instance
|
|
151
|
+
|
|
152
|
+
cdef inline heap_page* c_extend(self, size_t capacity=0, pthread_mutex_t* lock=NULL):
|
|
153
|
+
if not self.allocator:
|
|
154
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
155
|
+
return c_heap_allocator_extend(self.allocator, capacity, lock)
|
|
156
|
+
|
|
157
|
+
cdef inline void* c_calloc(self, size_t size, pthread_mutex_t* lock=NULL):
|
|
158
|
+
if not self.allocator:
|
|
159
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
160
|
+
return c_heap_calloc(self.allocator, size, lock)
|
|
161
|
+
|
|
162
|
+
cdef inline void* c_request(self, size_t size, int scan_all_pages=1, pthread_mutex_t* lock=NULL):
|
|
163
|
+
if not self.allocator:
|
|
164
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
165
|
+
return c_heap_request(self.allocator, size, scan_all_pages, lock)
|
|
166
|
+
|
|
167
|
+
cdef inline void c_free(self, void* ptr, pthread_mutex_t* lock=NULL):
|
|
168
|
+
if not self.allocator:
|
|
169
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
170
|
+
c_heap_free(ptr, lock)
|
|
171
|
+
|
|
172
|
+
cpdef HeapMemoryPage extend(self, size_t capacity=0, bint with_lock=True):
|
|
173
|
+
if not self.allocator:
|
|
174
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
175
|
+
cdef pthread_mutex_t* lock = &self.allocator.lock if with_lock else NULL
|
|
176
|
+
cdef heap_page* page = c_heap_allocator_extend(self.allocator, capacity, lock)
|
|
177
|
+
if not page:
|
|
178
|
+
raise OSError(errno, f'<{self.__class__.__name__}> failed to extend new page')
|
|
179
|
+
return HeapMemoryPage.c_from_header(page)
|
|
180
|
+
|
|
181
|
+
cpdef HeapMemoryBlock calloc(self, size_t size, bint with_lock=True):
|
|
182
|
+
if not self.allocator:
|
|
183
|
+
raise RuntimeError(f"Uninitialized <{self.__class__.__name__}>")
|
|
184
|
+
cdef pthread_mutex_t* lock = &self.allocator.lock if with_lock else NULL
|
|
185
|
+
cdef void* p = c_heap_calloc(self.allocator, size, lock)
|
|
186
|
+
if not p:
|
|
187
|
+
raise OSError(errno, f"<{self.__class__.__name__}> failed to calloc new buffer")
|
|
188
|
+
cdef heap_memory_block* block = <heap_memory_block*> (<char*> p - sizeof(heap_memory_block))
|
|
189
|
+
return HeapMemoryBlock.c_from_header(block, True)
|
|
190
|
+
|
|
191
|
+
cpdef HeapMemoryBlock request(self, size_t size, bint with_lock=True, bint scan_all_pages=True):
|
|
192
|
+
if not self.allocator:
|
|
193
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
194
|
+
cdef pthread_mutex_t* lock = &self.allocator.lock if with_lock else NULL
|
|
195
|
+
cdef void* p = c_heap_request(self.allocator, size, <int> scan_all_pages, lock)
|
|
196
|
+
if not p:
|
|
197
|
+
raise OSError(errno, f'<{self.__class__.__name__}> failed to request new buffer')
|
|
198
|
+
cdef heap_memory_block* block = <heap_memory_block*> (<char*> p - sizeof(heap_memory_block))
|
|
199
|
+
return HeapMemoryBlock.c_from_header(block, True)
|
|
200
|
+
|
|
201
|
+
cpdef void free(self, HeapMemoryBlock buffer, bint with_lock=True):
|
|
202
|
+
if not self.allocator:
|
|
203
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
204
|
+
if not buffer or not buffer.block:
|
|
205
|
+
return
|
|
206
|
+
cdef pthread_mutex_t* lock = &buffer.block.parent_page.allocator.lock if with_lock else NULL
|
|
207
|
+
c_heap_free(<void*> buffer.block.buffer, lock)
|
|
208
|
+
buffer.owner = False
|
|
209
|
+
buffer.block = NULL
|
|
210
|
+
|
|
211
|
+
cpdef void reclaim(self, bint with_lock=True):
|
|
212
|
+
if not self.allocator:
|
|
213
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
214
|
+
cdef pthread_mutex_t* lock = &self.allocator.lock if with_lock else NULL
|
|
215
|
+
c_heap_reclaim(self.allocator, lock)
|
|
216
|
+
|
|
217
|
+
def pages(self):
|
|
218
|
+
if not self.allocator:
|
|
219
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
220
|
+
cdef heap_page* page = self.allocator.active_page
|
|
221
|
+
while page:
|
|
222
|
+
yield HeapMemoryPage.c_from_header(page)
|
|
223
|
+
page = page.prev
|
|
224
|
+
|
|
225
|
+
def allocated(self):
|
|
226
|
+
if not self.allocator:
|
|
227
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
228
|
+
cdef heap_page* page = self.allocator.active_page
|
|
229
|
+
cdef heap_memory_block* block
|
|
230
|
+
while page:
|
|
231
|
+
block = page.allocated
|
|
232
|
+
while block:
|
|
233
|
+
yield HeapMemoryBlock.c_from_header(block, False)
|
|
234
|
+
block = block.next_allocated
|
|
235
|
+
page = page.prev
|
|
236
|
+
|
|
237
|
+
def free_list(self):
|
|
238
|
+
if not self.allocator:
|
|
239
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
240
|
+
cdef heap_memory_block* block
|
|
241
|
+
cdef size_t bin
|
|
242
|
+
for bin in range(AP_HEAP_BIN_COUNT):
|
|
243
|
+
block = self.allocator.bins[bin]
|
|
244
|
+
while block:
|
|
245
|
+
yield HeapMemoryBlock.c_from_header(block, False)
|
|
246
|
+
block = block.next_free
|
|
247
|
+
|
|
248
|
+
property mapped_pages:
|
|
249
|
+
def __get__(self):
|
|
250
|
+
if not self.allocator:
|
|
251
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
252
|
+
return <size_t> self.allocator.mapped_pages
|
|
253
|
+
|
|
254
|
+
property active_page:
|
|
255
|
+
def __get__(self):
|
|
256
|
+
if not self.allocator:
|
|
257
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}> or no active page')
|
|
258
|
+
elif not self.allocator.active_page:
|
|
259
|
+
return None
|
|
260
|
+
return HeapMemoryPage.c_from_header(self.allocator.active_page)
|
|
261
|
+
|
|
262
|
+
property autopage_capacity:
|
|
263
|
+
def __get__(self):
|
|
264
|
+
if not self.allocator:
|
|
265
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
266
|
+
return <size_t> self.allocator.autopage_capacity
|
|
267
|
+
|
|
268
|
+
def __set__(self, size_t value):
|
|
269
|
+
if not self.allocator:
|
|
270
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
271
|
+
self.allocator.autopage_capacity = value
|
|
272
|
+
|
|
273
|
+
property autopage_capacity_max:
|
|
274
|
+
def __get__(self):
|
|
275
|
+
if not self.allocator:
|
|
276
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
277
|
+
return <size_t> self.allocator.autopage_capacity_max
|
|
278
|
+
|
|
279
|
+
def __set__(self, size_t value):
|
|
280
|
+
if not self.allocator:
|
|
281
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
282
|
+
self.allocator.autopage_capacity_max = value
|
|
283
|
+
|
|
284
|
+
property autopage_alignment:
|
|
285
|
+
def __get__(self):
|
|
286
|
+
if not self.allocator:
|
|
287
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
288
|
+
return <size_t> self.allocator.autopage_alignment
|
|
289
|
+
|
|
290
|
+
def __set__(self, size_t value):
|
|
291
|
+
if not self.allocator:
|
|
292
|
+
raise RuntimeError(f'Uninitialized <{self.__class__.__name__}>')
|
|
293
|
+
self.allocator.autopage_alignment = value
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
cdef HeapAllocator ALLOCATOR = HeapAllocator()
|
|
297
|
+
ALLOCATOR.owner = False
|
|
298
|
+
cdef heap_allocator* C_ALLOCATOR = ALLOCATOR.allocator
|
|
299
|
+
|
|
300
|
+
globals()['ALLOCATOR'] = ALLOCATOR
|
|
301
|
+
globals()['DEFAULT_AUTOPAGE_CAPACITY'] = AP_HEAP_AUTOPAGE_CAPACITY
|
|
302
|
+
globals()['MAX_AUTOPAGE_CAPACITY'] = AP_HEAP_AUTOPAGE_CAPACITY_MAX
|
|
303
|
+
globals()['DEFAULT_AUTOPAGE_ALIGNMENT'] = AP_HEAP_AUTOPAGE_ALIGNMENT
|