#include <sys/types.h>
#include <iostream>
#include <queue>
#include <vector>


class NextOnFreeList {
public:
    NextOnFreeList *next;
};

class Event
{
	public:
		enum Event_Types {PROCESS,DATA};
		Event_Types Type;
		virtual ~Event() {}
		uint64_t timeIdx;
		virtual void process(void) {}
		
		static NextOnFreeList *freeList;
		inline void *operator new(size_t size);
		inline void operator delete(void *doomed, size_t size);
		static void newMemPool() { expandTheFreeList(); }
		static void expandTheFreeList();
		enum { EXPANSION_SIZE = 32};
};

inline void * Event::operator new(size_t size)
{
    if (0 == freeList) {// If the list is empty, fill it up.
        expandTheFreeList();
    }
     NextOnFreeList *head = freeList;
     freeList = head->next;
//	std::cout << "s " << size << "\n";
     return head;
}

inline void Event::operator delete(void *doomed, size_t size)
{
//    NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed);
    NextOnFreeList *head = (NextOnFreeList *)doomed;
    head->next = freeList;
    freeList = head;
}

void Event::expandTheFreeList()
{
    // We must allocate an object large enough to contain the next
    // pointer.
    size_t size = (64 > sizeof(NextOnFreeList *)) ?
        64 : sizeof(NextOnFreeList *);
    NextOnFreeList *runner = (NextOnFreeList*)malloc(size);
    freeList =  runner;
  for (int i = 0; i < EXPANSION_SIZE; i++) {
      runner->next = (NextOnFreeList*)malloc(size);
      runner = runner->next;
  }
  runner->next = 0;
}

NextOnFreeList *Event::freeList = 0;

class Event_InsertFlit: public Event
{
	public:
		Event_InsertFlit(uint64_t time, void *_from,
			void *_to, void *linkp);
		void process(void);
	private:
		void *from;
		void *to;
		void *lp_to_send;
};

Event_InsertFlit::Event_InsertFlit(uint64_t time, void *_from,
	void *_to, void *linkp)
{
	Type = DATA;
	timeIdx = time;
	to = _to;
	from = _from;
	lp_to_send = linkp;
}
void Event_InsertFlit::process(void)
{
	std::cout << "nothing\n";
}


int main(int argc, char argv[])
{
	Event *ev[1001];

	std::cout << "size " << sizeof(Event_InsertFlit)<< "\n";

	for(uint32_t i=0; i<1000;i++) {
		for(uint32_t j=0; j<1000;j++) {
			ev[j] = new Event_InsertFlit(1,NULL,NULL,NULL);
		}
		
		ev[1000] = new Event_InsertFlit(1,NULL,NULL,NULL);
		for(uint32_t j=0; j<10000;j++) {
			Event *temp=ev[1000];
			ev[1000] = new Event_InsertFlit(1,NULL,NULL,NULL);
			delete temp;
		}
		delete ev[1000];
		
		for(uint32_t j=0; j<1000;j++) {
			delete ev[j];
		}
	}
}

