[Python-checkins] peps: PEP 445: cleanup and inline examples

victor.stinner python-checkins at python.org
Tue Jun 18 01:30:24 CEST 2013


http://hg.python.org/peps/rev/14bdb8297ae8
changeset:   4936:14bdb8297ae8
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Jun 18 01:30:05 2013 +0200
summary:
  PEP 445: cleanup and inline examples

files:
  pep-0445.txt                |  154 ++++++++++++++++-------
  pep-0445/alloc_hooks.c      |  114 -----------------
  pep-0445/replace_allocs.c   |   44 ------
  pep-0445/replace_pymalloc.c |   34 -----
  4 files changed, 107 insertions(+), 239 deletions(-)


diff --git a/pep-0445.txt b/pep-0445.txt
--- a/pep-0445.txt
+++ b/pep-0445.txt
@@ -80,114 +80,178 @@
 Examples
 ========
 
-Use case 1: replace memory allocators, keeping pymalloc
--------------------------------------------------------
+Use case 1: Replace Memory Allocators, keep pymalloc
+----------------------------------------------------
 
 Setup your custom memory allocators, keeping pymalloc::
 
-    /* global variable, don't use a variable allocated on the stack! */
-    int magic = 42;
+    #include <stdlib.h>
 
-    int my_malloc(void *ctx, size_t size);
-    int my_realloc(void *ctx, void *ptr, size_t new_size);
-    void my_free(void *ctx, void *ptr);
+    int alloc_padding = 2;
+    int arena_padding = 10;
 
-    int my_alloc_arena(void *ctx, size_t size);
-    int my_free_arena(void *ctx, void *ptr, size_t size);
+    void* my_malloc(void *ctx, size_t size)
+    {
+        int padding = *(int *)ctx;
+        return malloc(size + padding);
+    }
+
+    void* my_realloc(void *ctx, void *ptr, size_t new_size)
+    {
+        int padding = *(int *)ctx;
+        return realloc(ptr, new_size + padding);
+    }
+
+    void my_free(void *ctx, void *ptr)
+    {
+        free(ptr);
+    }
+
+    void* my_alloc_arena(void *ctx, size_t size)
+    {
+        int padding = *(int *)ctx;
+        return malloc(size + padding);
+    }
+
+    void my_free_arena(void *ctx, void *ptr, size_t size)
+    {
+        free(ptr);
+    }
 
     void setup_custom_allocators(void)
     {
         PyMemAllocators alloc;
-        alloc.ctx = &magic;
+
+        alloc.ctx = &alloc_padding;
         alloc.malloc = my_malloc;
         alloc.realloc = my_realloc;
         alloc.free = my_free;
 
         PyMem_SetRawAllocators(&alloc);
         PyMem_SetAllocators(&alloc);
-        _PyObject_SetArenaAllocators(&magic, my_alloc_arena, my_free_arena);
+
+        _PyObject_SetArenaAllocators(&arena_padding,
+                                     my_alloc_arena, my_free_arena);
 
         PyMem_SetupDebugHooks();
     }
 
 .. warning::
-   Remove call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators are
-   not thread-safe.
+   Remove the call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators
+   are not thread-safe.
 
-Full example:
-`replace_allocs.c <http://hg.python.org/peps/file/tip/pep-0445/replace_allocs.c>`_.
 
-
-Use case 2: replace memory allocators, overriding pymalloc
+Use case 2: Replace Memory Allocators, overriding pymalloc
 ----------------------------------------------------------
 
 If your allocator is optimized for allocation of small objects (less than 512
 bytes) with a short liftime, you can replace override pymalloc (replace
 ``PyObject_Malloc()``).  Example::
 
-    /* global variable, don't use a variable allocated on the stack! */
-    int magic = 42;
+    #include <stdlib.h>
 
-    int my_malloc(void *ctx, size_t size);
-    int my_realloc(void *ctx, void *ptr, size_t new_size);
-    void my_free(void *ctx, void *ptr);
+    int padding = 2;
+
+    void* my_malloc(void *ctx, size_t size)
+    {
+        int padding = *(int *)ctx;
+        return malloc(size + padding);
+    }
+
+    void* my_realloc(void *ctx, void *ptr, size_t new_size)
+    {
+        int padding = *(int *)ctx;
+        return realloc(ptr, new_size + padding);
+    }
+
+    void my_free(void *ctx, void *ptr)
+    {
+        free(ptr);
+    }
 
     void setup_custom_allocators(void)
     {
         PyMemAllocators alloc;
-        alloc.ctx = &magic;
+        alloc.ctx = &padding;
         alloc.malloc = my_malloc;
         alloc.realloc = my_realloc;
         alloc.free = my_free;
 
         PyMem_SetRawAllocators(&alloc);
         PyMem_SetAllocators(&alloc);
-        PyObject_SetAllocators(&areana);
+        PyObject_SetAllocators(&alloc);
+
         PyMem_SetupDebugHooks();
     }
 
-Full example:
-`replace_pymalloc.c <http://hg.python.org/peps/file/tip/pep-0445/replace_pymalloc.c>`_.
+.. warning::
+   Remove the call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators
+   are not thread-safe.
 
 
-Use case 3: hook allocators
----------------------------
+
+Use case 3: Setup Allocator Hooks
+---------------------------------
 
 Setup hooks on memory allocators::
 
-    /* global variable, don't use a variable allocated on the stack! */
     struct {
         PyMemAllocators pymem;
         PyMemAllocators pymem_raw;
         PyMemAllocators pyobj;
-        int magic;
+        /* ... */
     } hook;
 
-    int hook_malloc(void *ctx, size_t size);
-    int hook_realloc(void *ctx, void *ptr, size_t new_size);
-    void hook_free(void *ctx, void *ptr);
+    static void* hook_malloc(void *ctx, size_t size)
+    {
+        PyMemAllocators *alloc = (PyMemAllocators *)ctx;
+        /* ... */
+        ptr = alloc->malloc(alloc->ctx, size);
+        /* ... */
+        return ptr;
+    }
 
-    /* Must be called before the first allocation, or hook_realloc() and
-       hook_free() will crash */
-    void setup_custom_allocators(void)
+    static void* hook_realloc(void *ctx, void *ptr, size_t new_size)
+    {
+        PyMemAllocators *alloc = (PyMemAllocators *)ctx;
+        void *ptr2;
+        /* ... */
+        ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
+        /* ... */
+        return ptr2;
+    }
+
+    static void hook_free(void *ctx, void *ptr)
+    {
+        PyMemAllocators *alloc = (PyMemAllocators *)ctx;
+        /* ... */
+        alloc->free(alloc->ctx, ptr);
+        /* ... */
+    }
+
+    void setup_hooks(void)
     {
         PyMemAllocators alloc;
+        static int registered = 0;
 
-        alloc.ctx = &magic;
+        if (registered)
+            return;
+        registered = 1;
+
         alloc.malloc = hook_malloc;
         alloc.realloc = hook_realloc;
         alloc.free = hook_free;
 
-        PyMem_GetRawAllocators(&alloc.pymem_raw);
-        alloc.ctx = &alloc.pymem_raw;
+        PyMem_GetRawAllocators(&hook.pymem_raw);
+        alloc.ctx = &hook.pymem_raw;
         PyMem_SetRawAllocators(&alloc);
 
-        PyMem_GetAllocators(&alloc.pymem);
-        alloc.ctx = &alloc.pymem;
+        PyMem_GetAllocators(&hook.pymem);
+        alloc.ctx = &hook.pymem;
         PyMem_SetAllocators(&alloc);
 
-        PyObject_GetAllocators(&alloc.pyobj);
-        alloc.ctx = &alloc.pyobj;
+        PyObject_GetAllocators(&hook.pyobj);
+        alloc.ctx = &hook.pyobj;
         PyObject_SetAllocators(&alloc);
     }
 
@@ -195,10 +259,6 @@
    No need to call ``PyMem_SetupDebugHooks()``: it is already installed by
    default.
 
-Full example tracking memory usage:
-`alloc_hooks.c <http://hg.python.org/peps/file/tip/pep-0445/alloc_hooks.c>`_.
-
-
 
 Performances
 ============
diff --git a/pep-0445/alloc_hooks.c b/pep-0445/alloc_hooks.c
deleted file mode 100644
--- a/pep-0445/alloc_hooks.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* global variable, don't use a variable allocated on the stack! */
-struct {
-    PyMemAllocators pymem;
-    PyMemAllocators pymem_raw;
-    PyMemAllocators pyobj;
-    size_t allocated;
-} hook;
-
-/* read_size_t() and write_size_t() are not needed if malloc() and realloc()
-   always return a pointer aligned to sizeof(size_t) bytes */
-static size_t read_size_t(const void *p)
-{
-    const unsigned char *q = (const unsigned char *)p;
-    size_t result = *q++;
-    int i;
-
-    for (i = SST; --i > 0; ++q)
-        result = (result << 8) | *q;
-    return result;
-}
-
-static void write_size_t(void *p, size_t n)
-{
-    unsigned char *q = (unsigned char *)p + SST - 1;
-    int i;
-
-    for (i = SST; --i >= 0; --q) {
-        *q = (unsigned char)(n & 0xff);
-        n >>= 8;
-    }
-}
-
-static int hook_malloc(void *ctx, size_t size)
-{
-    PyMemAllocators *alloc;
-    char *ptr;
-
-    size += sizeof(size_t);
-    ptr = alloc->malloc(size);
-    if (ptr != NULL) {
-        write_size_t(ptr, size);
-        ptr += sizeof(size_t);
-        allocated += size;
-    }
-    return ptr;
-}
-
-static int hook_realloc(void *ctx, void *void_ptr, size_t new_size)
-{
-    PyMemAllocators *alloc;
-    char *ptr, *ptr2;
-    size_t old_size;
-
-    ptr = void_ptr;
-    if (ptr) {
-        ptr -= sizeof(size_t);
-        old_size = read_size_t(ptr);
-    }
-    else {
-        old_size = 0;
-    }
-
-    ptr2 = alloc->realloc(ptr, size);
-    if (ptr2 != NULL) {
-        write_size_t(ptr2, size);
-        ptr2 += sizeof(size_t);
-        allocated -= old_size;
-        allocated += new_size;
-    }
-    return ptr2;
-}
-
-static void hook_free(void *ctx, void *void_ptr)
-{
-    PyMemAllocators *alloc;
-    char *ptr;
-    size_t size;
-
-    ptr = void_ptr;
-    if (!ptr)
-        return;
-
-    ptr -= sizeof(size_t);
-    size = read_size_t(ptr);
-
-    alloc->free(ptr);
-    allocated -= size;
-}
-
-/* Must be called before the first allocation, or hook_realloc() and
-   hook_free() will crash */
-void setup_custom_allocators(void)
-{
-    PyMemAllocators alloc;
-
-    alloc.malloc = my_malloc;
-    alloc.realloc = my_realloc;
-    alloc.free = my_free;
-
-    /* disabled: the hook is not thread-safe */
-#if 0
-    PyMem_GetRawAllocators(&alloc.pymem_raw);
-    alloc.ctx = &alloc.pymem_raw;
-    PyMem_SetRawAllocators(&alloc);
-#endif
-
-    PyMem_GetAllocators(&alloc.pymem);
-    alloc.ctx = &alloc.pymem;
-    PyMem_SetAllocators(&alloc);
-
-    PyObject_GetAllocators(&alloc.pyobj);
-    alloc.ctx = &alloc.pyobj;
-    PyObject_SetAllocators(&alloc);
-}
diff --git a/pep-0445/replace_allocs.c b/pep-0445/replace_allocs.c
deleted file mode 100644
--- a/pep-0445/replace_allocs.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdlib.h>
-
-/* global variable, don't use a variable allocated on the stack! */
-int magic = 42;
-
-int my_malloc(void *ctx, size_t size)
-{
-    return malloc(size);
-}
-
-int my_realloc(void *ctx, void *ptr, size_t new_size)
-{
-    return realloc(ptr, new_size);
-}
-
-void my_free(void *ctx, void *ptr)
-{
-    free(ptr);
-}
-
-int my_alloc_arena(void *ctx, size_t size)
-{
-    return malloc(size);
-}
-
-int my_free_arena(void *ctx, void *ptr, size_t size)
-{
-    free(ptr);
-}
-
-void setup_custom_allocators(void)
-{
-    PyMemAllocators alloc;
-    alloc.ctx = &magic;
-    alloc.malloc = my_malloc;
-    alloc.realloc = my_realloc;
-    alloc.free = my_free;
-
-    PyMem_SetRawAllocators(&alloc);
-    PyMem_SetAllocators(&alloc);
-    _PyObject_SetArenaAllocators(&magic, my_alloc_arena, my_free_arena);
-    PyMem_SetupDebugHooks();
-}
-
diff --git a/pep-0445/replace_pymalloc.c b/pep-0445/replace_pymalloc.c
deleted file mode 100644
--- a/pep-0445/replace_pymalloc.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <stdlib.h>
-
-/* global variable, don't use a variable allocated on the stack! */
-int magic = 42;
-
-int my_malloc(void *ctx, size_t size)
-{
-    return malloc(size);
-}
-
-int my_realloc(void *ctx, void *ptr, size_t new_size)
-{
-    return realloc(ptr, new_size);
-}
-
-void my_free(void *ctx, void *ptr)
-{
-    free(ptr);
-}
-
-void setup_custom_allocators(void)
-{
-    PyMemAllocators alloc;
-    alloc.ctx = &magic;
-    alloc.malloc = my_malloc;
-    alloc.realloc = my_realloc;
-    alloc.free = my_free;
-
-    PyMem_SetRawAllocators(&alloc);
-    PyMem_SetAllocators(&alloc);
-    PyObject_SetAllocators(&areana);
-    PyMem_SetupDebugHooks();
-}
-

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list