This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC 1/2] Adding custom destructor for free.


Hi,

For improving malloc a nice feature would be ability to assign a
function to a pointer that would do a custom free logic when called.

I wrote a proof-of-concept implementation to get comments, its interface
is

void *
dmalloc (size_t size, void *data, 
         void (*destroy)(void *p, void *size, void *data, void (*freep)(void *)))

This call returns a pointer that when a free of that pointer is called a
function destroy is invoked with size and data received by dmalloc.

Third argument is a pointer to original free routine, and function can
but does not have to free data by this function.

I have three applications in mind and will send a
prototypes that use this.

A major one is adding generic memory pool. Users often add a memory pool
to improve performance or to decrease memory overhead at cost of maintainability
and making memory usage less liquid.

Goal is provide a memory pool they can use to satisfy their needs which
has some added benefits, one is thread safety and effective returning
memory from other thread than original one.

Second application would be reference counting in c. It would allow to
return a char * strings that are shared and can be freed.

Third trick would be malloca that could be freed by a standard free
function (by making a stack destructor nop). This would be handy for
automatic conversion of heap allocation to stack-like conversion (which
could use alternative stack/split stack to satisfy large requests.)

I wonder if this would be a core functionality or by adding new
library?

Other comments?

#define _GNU_SOURCE
#include <dlfcn.h>
#include <malloc.h>
#include <stdint.h>
#define SENTINEL 8040899990803335949L
static int inited;
struct header
{
  void *data;
  size_t size;
  void (*destroy)(void *, void *, void *, void (*)(void *));
  uint64_t sentinel;
};
static void *(*reallocp)(void *, size_t);
static void (*freep)(void *);
static void
init ()
{
  reallocp = dlsym (RTLD_NEXT, "realloc");
  freep = dlsym (RTLD_NEXT, "free");
  inited = 1;
}

void *
dmalloc (size_t s, void *data, void (*destroy)(void *, void *, void *, void (*)(void *)))
{
  if (s > s + sizeof (struct header))
    return NULL;

  struct header *h = malloc (s + sizeof (struct header));
  if (!h)
    return NULL;

  h->size = s;
  h->data = data;
  h->destroy = destroy;
  h->sentinel = SENTINEL;
  return h + 1;
}

void *
realloc (void *p, size_t s)
{
  struct header *h = (struct header *) p;
  h--;
  if (h->sentinel == SENTINEL)
    return reallocp (h, s + sizeof (struct header));
  else
    return reallocp (p, s);
}

void
free (void *p)
{
  if (!inited)
    init ();
  if (!p)
    return;

  struct header *h = (struct header *) p;
  h--;
  if (h->sentinel == SENTINEL)
    h->destroy ((void *) h, h->size, h->data , freep);
  else
    freep (p);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]