// file: memory_manager.h
//

// make sure definitions are only made once
//
#ifndef __ISIP_MEMORY_MANAGER
#define __ISIP_MEMORY_MANAGER

// isip include files
//
#ifndef __ISIP_INTEGRAL
#include <integral.h>
#endif

// forward declaration of classes
//
#ifndef __ISIP_LINK_NODE
#include <link_node.h>
#endif

class Trace;
class Lex_node;
class Lattice_node;
class Lattice_path;
class Ngram_node;
class Hash_cell;
class History;
class Instance;

// Memory_manager: a class that handles memory allocation and deletion
// for traces and link list nodes
//
class Memory_manager {
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:
  
  // pointer to a list of free node pointers and the count of node
  // pointers left on the free node list
  //
  Link_node* node_list_d;
  int_4 node_count_d;
  int_4 num_node_d;
  
  // pointer to a list of free traces and the count of traces left on
  // the free trace list
  //
  Link_node* trace_list_d;
  int_4 trace_count_d;
  int_4 num_trace_d;

  // pointer to a list of lexical tree nodes
  //
  Link_node* lex_list_d;
  int_4 lex_count_d;
  int_4 num_lex_d;
  
  // pointer to a list of lattice nodes
  //
  Link_node* lat_list_d;
  int_4 lat_count_d;
  int_4 num_lat_d;
  
  // pointer to a list of lattice path nodes
  //
  Link_node* lpath_list_d;
  int_4 lpath_count_d;
  int_4 num_lpath_d;
  
  // pointer to a list of ngram nodes
  //
  Link_node* ngram_list_d;
  int_4 ngram_count_d;
  int_4 num_ngram_d;
  
  // pointer to a list of hash table cells
  //
  Link_node* hash_list_d;
  int_4 hash_count_d;
  int_4 num_hash_d;

  // pointer to a list of history nodes
  //
  Link_node* hist_list_d;
  int_4 hist_count_d;
  int_4 num_hist_d;

  // pointer to a list of instances
  //
  Link_node* instance_list_d;
  int_4 instance_count_d;
  int_4 num_instance_d;
  
  // the number of nodes or traces to allocate if one of the free
  // lists becomes empty
  //
  int_4 node_grow_size_d;
  int_4 trace_grow_size_d;  
  int_4 lex_grow_size_d;
  int_4 lat_grow_size_d;
  int_4 lpath_grow_size_d;
  int_4 ngram_grow_size_d;
  int_4 hash_grow_size_d;
  int_4 hist_grow_size_d;
  int_4 instance_grow_size_d;
  
  //---------------------------------------------------------------------------
  //
  // public methods
  //
  //---------------------------------------------------------------------------
public:

  // required methods
  //
  char_1* name_cc();
  volatile void error_handler_cc(char_1* method_name, char_1* message);
  logical_1 debug_cc(FILE* fp, char_1* message);
  int_4 size_cc();
  
  // destructors/constructors
  //
  ~Memory_manager();  
  Memory_manager();                                         // default
  Memory_manager(int_4 grow_size, int_4 node_size);         // overloaded
  Memory_manager(const Memory_manager& manager);            // copy

  // methods that take memory units off of the free lists and give
  // them to the user
  //
  Link_node* new_node_cc();
  Trace* new_trace_cc();
  Lex_node* new_lex_cc();
  Lattice_node* new_lat_cc();
  Lattice_path* new_lpath_cc();
  Ngram_node* new_ngram_cc();
  Hash_cell* new_hash_cc();
  History* new_hist_cc();
  Instance* new_instance_cc();
  
  // methods that put memory units back on the free lists
  //
  logical_1 delete_cc(Link_node* node);  
  logical_1 delete_cc(Trace* trace);
  logical_1 delete_cc(Lex_node* lxn);
  logical_1 delete_cc(Lattice_node* ltn);
  logical_1 delete_cc(Lattice_path* lpth);
  logical_1 delete_cc(Ngram_node* ngn);
  logical_1 delete_cc(Hash_cell* hash);
  logical_1 delete_cc(History* hist);
  logical_1 delete_cc(Instance* inst);

  // set methods
  //
  logical_1 set_node_grow_size_cc(int_4 size);  
  logical_1 set_trace_grow_size_cc(int_4 size);
  logical_1 set_lex_grow_size_cc(int_4 size);
  logical_1 set_lat_grow_size_cc(int_4 size);
  logical_1 set_lpath_grow_size_cc(int_4 size);
  logical_1 set_ngram_grow_size_cc(int_4 size);
  logical_1 set_hash_grow_size_cc(int_4 size);
  logical_1 set_hist_grow_size_cc(int_4 size);
  logical_1 set_instance_grow_size_cc(int_4 size);

  // get methods
  //
  int_4 get_node_grow_size_cc();
  int_4 get_trace_grow_size_cc();
  int_4 get_lex_grow_size_cc();
  int_4 get_lat_grow_size_cc();
  int_4 get_lpath_grow_size_cc();
  int_4 get_ngram_grow_size_cc();
  int_4 get_hash_grow_size_cc();
  int_4 get_hist_grow_size_cc();
  int_4 get_instance_grow_size_cc();

  // count methods
  //
  int_4 get_node_count_cc();
  int_4 get_trace_count_cc();
  int_4 get_lex_count_cc();
  int_4 get_lat_count_cc();
  int_4 get_lpath_count_cc();
  int_4 get_ngram_count_cc();
  int_4 get_hash_count_cc();
  int_4 get_hist_count_cc();
  int_4 get_instance_count_cc();

  // total number methods
  //
  int_4 get_num_node_cc();
  int_4 get_num_trace_cc();
  int_4 get_num_lex_cc();
  int_4 get_num_lat_cc();
  int_4 get_num_lpath_cc();
  int_4 get_num_ngram_cc();
  int_4 get_num_hash_cc();
  int_4 get_num_hist_cc();
  int_4 get_num_instance_cc();  

  // method to reorder the memory blocks so they are contiguously ordered
  // this is useful when memory gets scattered in the internal lists due
  // to many random accesses of memory locales.
  //
  logical_1 reorder_blocks_cc();
  static int item_sort_cc(Link_node** first_a, Link_node** second_a);
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // methods to allocate more memory for the free traces list and the
  // free nodes list
  //
  logical_1 grow_node_cc();
  logical_1 grow_trace_cc();  
  logical_1 grow_lex_cc();  
  logical_1 grow_lat_cc();  
  logical_1 grow_lpath_cc();  
  logical_1 grow_ngram_cc();  
  logical_1 grow_hash_cc();
  logical_1 grow_hist_cc();
  logical_1 grow_instance_cc();

  // method to sort memory hierarchy
  //
  logical_1 sort_nodes_cc(Link_node*& in_list, int_4 size);
};

// end of file
// 
#endif
