// Common, group Miscelaneous
// Copyright Alexander Liss

#ifndef __TASKTHREAD_H__
#define __TASKTHREAD_H__

#include <process.h>
#include "win0.h"


	// pass data in heap, thread procedure deletes it
	// callback is of a form void callback(const t&);

	// TaskThread
	// no control over TaskThread - fire and forget
	// do not have anything in callback that can stuck
	//  (a call to external lib, infinite loop, etc.)
	// an object has no data and 
	//  can be destructed before the end of the thread
	// if a reference to a counter is passed
	//  then the counter is updated


template<class T>
class TaskThread
{
public:
 static int launch(void (*callback)(const T&),T *z=0,long *counter=0);
private:
 struct H{void (*callback)(const T&);T* data; long *counter;};
 static void _cdecl thread_procedure(void *);
};



	// TaskThread

template<class T>
void _cdecl TaskThread<T>::thread_procedure(void * ptr)
{
 TaskThread<T>::H * h=static_cast< TaskThread<T>::H *>(ptr);
 h->callback(*h->data);
 delete h->data; 
 h->data=0;
 if(h->counter)
	 InterlockedDecrement(h->counter);
 delete h; 
 h=0;
}

template<class T>
int TaskThread<T>::launch(void (*f)(const T&),T *d,long *counter)
{
 H *h=new H;
 h->callback=f;
 h->data=d;
 h->counter=counter;
 if(counter)
	 InterlockedIncrement(counter);
 unsigned long g=_beginthread(thread_procedure,0,h);
 if(g==-1)
 {
	 InterlockedDecrement(counter);
	 return 1;
 }
 return 0;
}




/*

  // Usage

//#include "stdio.h"

  struct A{int i;};

  void callback(const A& z)
  { fprintf(stdout,"a = %d\n",z.i);}

  long counter=0;

void f()
{
	A *a = new A;
	a->i=1;

	TaskThread<A>::launch(callback,a,&counter);

	TaskThread<A>::launch(callback,a);
}

*/


#endif