forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpycore_freelist.h
111 lines (96 loc) · 3.01 KB
/
pycore_freelist.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#ifndef Py_INTERNAL_FREELIST_H
#define Py_INTERNAL_FREELIST_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
#include "pycore_freelist_state.h" // struct _Py_freelists
#include "pycore_interp_structs.h" // PyInterpreterState
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED()
#include "pycore_pystate.h" // _PyThreadState_GET
#include "pycore_stats.h" // OBJECT_STAT_INC
static inline struct _Py_freelists *
_Py_freelists_GET(void)
{
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
_Py_EnsureTstateNotNULL(tstate);
#endif
#ifdef Py_GIL_DISABLED
return &((_PyThreadStateImpl*)tstate)->freelists;
#else
return &tstate->interp->object_state.freelists;
#endif
}
// Pushes `op` to the freelist, calls `freefunc` if the freelist is full
#define _Py_FREELIST_FREE(NAME, op, freefunc) \
_PyFreeList_Free(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), \
Py_ ## NAME ## _MAXFREELIST, freefunc)
// Pushes `op` to the freelist, returns 1 if successful, 0 if the freelist is full
#define _Py_FREELIST_PUSH(NAME, op, limit) \
_PyFreeList_Push(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), limit)
// Pops a PyObject from the freelist, returns NULL if the freelist is empty.
#define _Py_FREELIST_POP(TYPE, NAME) \
_Py_CAST(TYPE*, _PyFreeList_Pop(&_Py_freelists_GET()->NAME))
// Pops a non-PyObject data structure from the freelist, returns NULL if the
// freelist is empty.
#define _Py_FREELIST_POP_MEM(NAME) \
_PyFreeList_PopMem(&_Py_freelists_GET()->NAME)
#define _Py_FREELIST_SIZE(NAME) (int)((_Py_freelists_GET()->NAME).size)
static inline int
_PyFreeList_Push(struct _Py_freelist *fl, void *obj, Py_ssize_t maxsize)
{
if (fl->size < maxsize && fl->size >= 0) {
FT_ATOMIC_STORE_PTR_RELAXED(*(void **)obj, fl->freelist);
fl->freelist = obj;
fl->size++;
OBJECT_STAT_INC(to_freelist);
return 1;
}
return 0;
}
static inline void
_PyFreeList_Free(struct _Py_freelist *fl, void *obj, Py_ssize_t maxsize,
freefunc dofree)
{
if (!_PyFreeList_Push(fl, obj, maxsize)) {
dofree(obj);
}
}
static inline void *
_PyFreeList_PopNoStats(struct _Py_freelist *fl)
{
void *obj = fl->freelist;
if (obj != NULL) {
assert(fl->size > 0);
fl->freelist = *(void **)obj;
fl->size--;
}
return obj;
}
static inline PyObject *
_PyFreeList_Pop(struct _Py_freelist *fl)
{
PyObject *op = _PyFreeList_PopNoStats(fl);
if (op != NULL) {
OBJECT_STAT_INC(from_freelist);
_Py_NewReference(op);
}
return op;
}
static inline void *
_PyFreeList_PopMem(struct _Py_freelist *fl)
{
void *op = _PyFreeList_PopNoStats(fl);
if (op != NULL) {
OBJECT_STAT_INC(from_freelist);
}
return op;
}
extern void _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization);
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_FREELIST_H */