//////////////////////////////////////////////////////////////
//   TestConstructor()                                      //
//   Author: Diego Faso                                     //
//   This macro is a simple example of threads constructor  //
//      and id management                                   //
//                                                          //
//   Deletion and Cleaning-Up are also tested.              //
//////////////////////////////////////////////////////////////

#include <Riostream.h>
#include "TThread.h"

void mycleanup1(void *arg){
  
  TThread::Printf("Custom cleanup (%d) called",(Int_t)arg);
}

void *handle1(void *ptr){

  TThread::Printf("Hello from thread %d",(Int_t) ptr);

  Int_t clean_push_ret = TThread::CleanUpPush((void *)&mycleanup1,(void *)999);
  TThread::Printf("clean_push_ret = %d",clean_push_ret);

  Bool_t PopUserFunc = 1; // true if you you want to pop out of the stack the user cleanup function
  Int_t PopExe = -1;
  PopExe = 1; // will execute (now) user cleanup function
  //PopExe = 0; // will not execute user cleanup function

  if(PopUserFunc){ // pop user cleanup function out of stack (with/without executing it now)
    Int_t clean_pop_ret = TThread::CleanUpPop(PopExe);
    TThread::Printf("clean_pop_ret = %d",clean_pop_ret);
  }
  ///////////////////////////////////////////////////////////////////////////
  // User cleanup method can be reloaded into the stack
  /*
    clean_push_ret = TThread::CleanUpPush((void *)&mycleanup1,(void *)999);
    TThread::Printf("clean_push_ret = %d",clean_push_ret);
  */
  ///////////////////////////////////////////////////////////////////////////

  for(Int_t i=0;i<30;i++){
    TThread::Printf("I'm thread %d: i = %d",ptr,i);
    usleep(100000);
  }
  TThread::Printf("Bye bye from thread %d",ptr);

  return 0;
}


void TestConstructor(){
#ifdef __CINT__
  cout << "This script can only be executed via ACliC:" << endl;
  gApplication->Terminate();
  return;
#endif


  TThread *th1 = new TThread("my_thread_1",handle1,(void *)1);
  TThread::Ps();


  th1->Run();

  TThread::Printf("Execution should be in progress");
  TThread::Ps();

  th1->Join(); // needed to make this macro work

  TThread::Ps();

  TThread::Printf("Now cleaning"); // not needed if the thread has already been cancelled (completed)
  th1->CleanUp(); // 
  TThread::Ps();

  // Exit will terminate the calling thread
  /*
  TThread::Printf("Now exiting thread");
  th1->Exit(); // will exit from application; NOTE: th1->Join() is needed
  TThread::Ps();
  */
  
  TThread::Printf("Now deleting");
  TThread::Delete(th1);
  delete th1; // not really needed
  th1 = 0;
  TThread::Printf("Bye bye...");

}

