#include "operatingsystem.h"
#include "c4d_memory.h"
#include "c4d_thread.h"

void XThreadMain(void *data)
{
	((Thread*)data)->Main();
}

Bool XThreadTest(void *data)
{
	return ((Thread*)data)->TestDBreak();
}

Thread::Thread(void)
{
	weak=FALSE;
	bt=C4DOS.Bt->Alloc(XThreadMain,XThreadTest,this);
}

Thread::~Thread(void)
{
	if (!weak) C4DOS.Bt->Free(bt);
}

Bool Thread::Start(Bool back, Bool pri)
{
	if (!bt) return FALSE;
	return C4DOS.Bt->Start(bt,back,pri);
}

void Thread::End(void)
{
	if (bt) C4DOS.Bt->End(bt);
}

void Thread::Wait(Bool checkevents)
{
	if (bt) C4DOS.Bt->Wait(bt,checkevents);
}

Semaphore *Semaphore::Alloc(void)
{
	return C4DOS.Bt->SMAlloc();
}

void Semaphore::Free(Semaphore *&sm)
{
	C4DOS.Bt->SMFree(sm);
	sm=NULL;
}

MPThread::MPThread(void) 
{ 
	mp=NULL; 
	mpcount=0;
}

MPThread::~MPThread(void)
{
	if (!mp) return;
	C4DOS.Bt->MPEnd(mp);
	C4DOS.Bt->MPFree(mp);
	mp=NULL;
}

Bool MPThread::Init(const Thread &parent, LONG count, Thread **thread)
{
	return Init(parent.Get(),count,thread);
}

Bool MPThread::Init(BaseThread *parent, LONG count, Thread **thread)
{
	if (mp) { C4DOS.Bt->MPFree(mp); mp=NULL; mpcount=0; }

	mpcount=count;
	mp=C4DOS.Bt->MPAlloc(parent,count,XThreadMain,XThreadTest,(void**)thread);

	LONG i;	
	for (i=0; i<count; i++)
	{
		if (!thread[i]->weak)
		{
			thread[i]->weak=TRUE;
			C4DOS.Bt->Free(thread[i]->bt);
		}
		thread[i]->bt=C4DOS.Bt->MPGetThread(mp,i);
	}

	return mp!=NULL;
}

Bool MPThread::Start(void)
{
	BaseThread *bt=NULL;
	LONG i;

	for (i=0; i<mpcount; i++)
	{
		bt=C4DOS.Bt->MPGetThread(mp,i);
		if (!bt || !C4DOS.Bt->Start(bt,TRUE,TRUE)) 
		{
			C4DOS.Bt->MPEnd(mp);
			return FALSE;
		}
	}

	return TRUE;
}

Thread *MPThread::WaitForNextFree(void)
{
	return (Thread*)C4DOS.Bt->MPWaitForNextFree(mp);
}

void MPThread::Wait(void)
{
	C4DOS.Bt->MPWait(mp);
}

void MPThread::End(void)
{
	C4DOS.Bt->MPEnd(mp);
}
