
class memory_management {

  friend class memory_management_init;

  int num;     // number of managers      (default   4)
  int tbl_sz;  // table size of managers  (default 256) 

  leda_mutex list_lock;
  leda_mutex empty_lock;

  memory_manager *head_free_list;

  void init(int n=4, int sz=256);
  void destroy();

public:

  memory_management() {}
  memory_management(int n, int sz) { init(n,sz); }
 ~memory_management() { destroy(); }

  int max_size()    { return tbl_sz; }
  int num_of_mgrs() { return num;    }
  
  void kill();
  void clear();
  void print_statistics();
  int  used_memory();
  
  memory_manager& acquire();
  void release(memory_manager&);
  
  void allocate_block(int,int);
  
  memory_elem_ptr allocate_words(int);
  memory_elem_ptr allocate_bytes(int);
  memory_elem_ptr allocate_bytes_with_check(int);
  
  void deallocate_words(void*,int);
  void deallocate_bytes(void*, int);
  void deallocate_bytes_with_check(void*,int);
  void deallocate_list(void*, void*, int);
};


extern memory_management std_memory_mgment;

class memory_management_init
{
  static unsigned count;

public:
  memory_management_init() { if (count++ == 0) std_memory_mgment.init(); }
 ~memory_management_init() { if (--count == 0) std_memory_mgment.kill(); }

};

static memory_management_init memory_initialize;



#define LEDA_MEMORY(type)\
\
void* operator new(size_t bytes)\
{ memory_manager &manager = std_memory_mgment.acquire();\
  memory_elem_ptr* q = manager.free_list+bytes;\
  if (*q==0) manager.allocate_block(bytes,-1);\
  memory_elem_ptr p = *q;\
  *q = p->next;\
  std_memory_mgment.release(manager);\
  return p;\
 }\
\
void* operator new(size_t,void* p) { return p; }\
void* operator new(size_t,void* p,int) { return p; }\
\
void  operator delete(void* p, size_t bytes)\
{ memory_manager &manager = std_memory_mgment.acquire();\
  memory_elem_ptr* q = manager.free_list+bytes;\
  memory_elem_ptr(p)->next = *q;\
  *q = memory_elem_ptr(p);\
  std_memory_mgment.release(manager);\
 }

#define LEDA_MEMORY_WITH_CHECK(type)\
void* operator new(size_t bytes)\
{ return std_memory_mgment.allocate_bytes_with_check(bytes); }\
\
void* operator new(size_t,void* p) { return p; }\
void* operator new(size_t,void* p,int) { return p; }\
\
void  operator delete(void* p,size_t bytes)\
{ std_memory_mgment.deallocate_bytes_with_check(p,bytes); }


