Repository: numpy/numpy
File: numpy/_core/src/multiarray/alloc.cpp (C++)

Code before:
# define NCACHE 7 /* number of cache entries per bucket */
/* this structure fits neatly into a cacheline */
typedef struct {
    npy_uintp available; /* number of cached pointers */
    void * ptrs[NCACHE];
} cache_bucket;

static thread_local cache_bucket datacache[NBUCKETS];
static thread_local cache_bucket dimcache[NBUCKETS_DIM];

typedef struct cache_destructor {
    ~cache_destructor() {
        for (npy_uint i = 0; i < NBUCKETS; ++i) {
            while (datacache[i].available > 0) {
                free(datacache[i].ptrs[--datacache[i].available]);
            }
        }
        for (npy_uint i = 0; i < NBUCKETS_DIM; ++i) {
            while (dimcache[i].available > 0) {
                PyArray_free(dimcache[i].ptrs[--dimcache[i].available]);
            }
        }
    }
} cache_destructor;

static thread_local cache_destructor tls_cache_destructor;

/*
 * This function tells whether NumPy attempts to call `madvise` with
 * `MADV_HUGEPAGE`.  `madvise` is only ever used on linux, so the value
 * of `madvise_hugepage` may be ignored.
 *
 * It is exposed to Python as `np._core.multiarray._get_madvise_hugepage`.
 */
NPY_NO_EXPORT PyObject *
_get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
{
#ifdef NPY_OS_LINUX
    if (npy_thread_unsafe_state.madvise_hugepage) {
        Py_RETURN_TRUE;
    }
#endif
    Py_RETURN_FALSE;
}


/*
 * This function enables or disables the use of `MADV_HUGEPAGE` on Linux
 * by modifying the global static `madvise_hugepage`.
 * It returns the previous value of `madvise_hugepage`.
 *

Review comment (suggestion):
if anyone is curious, the relevant bit of the C++ spec: https://timsong-cpp.github.io/cppwp/n4140/basic.start.term. Assuming the thread exits gracefully, this will be invoked on thread exit.

Code after:
# define NCACHE 7 /* number of cache entries per bucket */
/* this structure fits neatly into a cacheline */
typedef struct {
    npy_uintp available; /* number of cached pointers */
    void * ptrs[NCACHE];
} cache_bucket;

static NPY_TLS cache_bucket datacache[NBUCKETS];
static NPY_TLS cache_bucket dimcache[NBUCKETS_DIM];

typedef struct cache_destructor {
    ~cache_destructor() {
        for (npy_uint i = 0; i < NBUCKETS; ++i) {
            while (datacache[i].available > 0) {
                free(datacache[i].ptrs[--datacache[i].available]);
            }
        }
        for (npy_uint i = 0; i < NBUCKETS_DIM; ++i) {
            while (dimcache[i].available > 0) {
                PyArray_free(dimcache[i].ptrs[--dimcache[i].available]);
            }
        }
    }
} cache_destructor;

static NPY_TLS cache_destructor tls_cache_destructor;

/*
 * This function tells whether NumPy attempts to call `madvise` with
 * `MADV_HUGEPAGE`.  `madvise` is only ever used on linux, so the value
 * of `madvise_hugepage` may be ignored.
 *
 * It is exposed to Python as `np._core.multiarray._get_madvise_hugepage`.
 */
NPY_NO_EXPORT PyObject *
_get_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
{
#ifdef NPY_OS_LINUX
    if (npy_thread_unsafe_state.madvise_hugepage) {
        Py_RETURN_TRUE;
    }
#endif
    Py_RETURN_FALSE;
}


/*
 * This function enables or disables the use of `MADV_HUGEPAGE` on Linux
 * by modifying the global static `madvise_hugepage`.
 * It returns the previous value of `madvise_hugepage`.
 *