#include <rtl.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>

#define printf rtl_printf

int gettimeofday (struct timeval *TP, void *dummy)
{
  TP->tv_sec=0;
  TP->tv_usec=0;
  return 0;
}

#include <ul_gavl.h>
#include <ul_gavlcust.h>
#include <ul_gavlrepcust.h>
#include <ul_gavlflesint.h>

#undef GAVL_TEST_FLES

typedef struct cust2_item {
  int my_val;
  gavl_node_t my_node;
  int more_data;
} cust2_item_t;

typedef struct cust2_root {
 #ifndef GAVL_TEST_FLES
  gavl_cust_root_field_t my_root;
 #else /*GAVL_TEST_FLES*/
  gavl_fles_int_root_field_t my_root;
 #endif /*GAVL_TEST_FLES*/
  int my_info;
  int my_first_val;
  int my_last_val;
} cust2_root_t;

typedef int cust2_key_t;

/* Custom tree declarations */
/* GAVL_CUST_NODE_INT_DEC - standard custom tree with internal node */
/* GAVL_FLES_INT_DEC      - tree with enhanced first last access speed  */

#ifndef GAVL_TEST_FLES
GAVL_CUST_NODE_INT_DEC(cust2, cust2_root_t, cust2_item_t, cust2_key_t,
	my_root, my_node, my_val, cust2_cmp_fnc)
#else /*GAVL_TEST_FLES*/
GAVL_FLES_INT_DEC(cust2, cust2_root_t, cust2_item_t, cust2_key_t,
	my_root, my_node, my_val, cust2_cmp_fnc)
#endif /*GAVL_TEST_FLES*/

inline int
cust2_cmp_fnc(const cust2_key_t *a, const cust2_key_t *b)
{
  if (*a>*b) return 1;
  if (*a<*b) return -1;
  return 0;
}

/* Custom tree implementation */
/* GAVL_CUST_NODE_INT_IMP - version with strict ordering */
/* GAVL_CUST_NODE_INT_REP_IMP - version without strict ordering */
/* GAVL_FLES_INT_IMP      - tree with enhanced first last access speed  */

#ifndef GAVL_TEST_FLES
GAVL_CUST_NODE_INT_IMP(cust2, cust2_root_t, cust2_item_t, cust2_key_t,
	my_root, my_node, my_val, cust2_cmp_fnc)
#else /*GAVL_TEST_FLES*/
GAVL_FLES_INT_IMP(cust2, cust2_root_t, cust2_item_t, cust2_key_t,
	my_root, my_node, my_val, cust2_cmp_fnc, 0, 
	root->my_first_val=cust2_first(root)->my_val,
	root->my_last_val=cust2_first(root)->my_val, 
	)
#endif /*GAVL_TEST_FLES*/

cust2_root_t cust2_root;

#define CUST2_ITEMS_CNT 512

cust2_item_t cust2_items[CUST2_ITEMS_CNT];


void timing_test_print(struct timeval *start, struct timeval *stop, char *s)
{
  long sec, usec;
  sec=stop->tv_sec-start->tv_sec;
  usec=stop->tv_usec-start->tv_usec;
  if(usec>=1000000) {
    usec-=1000000;
    sec++;
  }
  if(usec<0) {
    usec+=1000000;
    sec--;
  }
  printf("%s :\t%4ld.%06ld\n",s,sec,usec);
}


void cust_timing_test(void)
{
  int i;
  int items_cnt=CUST2_ITEMS_CNT;
  cust2_item_t *items;
  struct timeval time_start, time_stop;

  printf("\nRunning custom tree timing test for %d items\n",items_cnt);
  
  items=cust2_items;
  
  for(i=0;i<items_cnt;i++){
    items[i].my_val=i;
    items[i].more_data=0;
  }
  
  gettimeofday(&time_start,NULL);
  for(i=0;i<items_cnt;i++){
    if(cust2_insert(&cust2_root,items+i)<0)
      printf("cust2_insert error\n");
  }
  gettimeofday(&time_stop,NULL);
  timing_test_print(&time_start,&time_stop,"cust insert");
  
  gettimeofday(&time_start,NULL);
  for(i=0;i<items_cnt;i++){
    if(!cust2_find(&cust2_root,&i))
      printf("cust2_find error\n");
  }
  gettimeofday(&time_stop,NULL);
  timing_test_print(&time_start,&time_stop,"cust find");

  gettimeofday(&time_start,NULL);
  for(i=0;i<items_cnt;i++){
    if(1){
      if(cust2_delete(&cust2_root,items+i)<0)
	printf("cust2_delete error\n");
    }else{
      if(!cust2_cut_first(&cust2_root))
	printf("cust2_cut_first NULL\n");
    }
  }
  gettimeofday(&time_stop,NULL);
  timing_test_print(&time_start,&time_stop,"cust delete");
}

/*===========================================================*/

pthread_t t1;

void * t1_routine(void *arg)
{
  cust_timing_test();

  while (1) {
    pthread_wait_np ();

  }
  return 0;
}


int init_module(void) {
        return pthread_create (&t1, NULL, t1_routine, 0);

}

void cleanup_module(void) {
        pthread_delete_np (t1);
}
