#include	"vthdr.h"

static char*    Version = "\n@(#)vthread (AT&T Labs - kpv) 2000-05-15\0\n";

/*	Open a thread handle
**
**	Written by Kiem-Phong Vo
*/

#if __STD_C
Vthread_t* vtopen(Vthread_t* vt, int flags)
#else
Vthread_t* vtopen(vt, flags)
Vthread_t*	vt;
int		flags
#endif
{
#if !vt_threaded
	return NIL(Vthread_t*);
#else
	Vthread_t*	v;
	int		s, slot;

	VTONCE();

	v = (Vthread_t*)Version; /* shut compiler warning */

	vtmtxlock(_Vtmutex);
	if(vt)
	{	/* if there is a running thread, wait for its termination */
		for(slot = 0; slot < _Vtnlist; ++slot)
			if(_Vtlist[slot] == vt)
				break;

		if(slot < _Vtnlist && (vt->state&VT_RUNNING) )
		{	vtmtxunlock(_Vtmutex);
			if(vtwait(vt) < 0)
				return NIL(Vthread_t*);
			vtmtxlock(_Vtmutex);
		}

		if(slot == _Vtnlist)
			goto find_slot;
	}
	else
	{ find_slot:
		for(slot = 0; slot < _Vtnlist; ++slot)
			if(_Vtlist[slot] == NIL(Vthread_t*))
				break;
	}

	/* create a slot for this new thread if necessary */
	if(slot >= _Vtnlist)
	{	Vthread_t** list;
#define INCR	8
		if(!(list = (Vthread_t**)malloc((slot+INCR)*sizeof(Vthread_t*))) )
		{	vtmtxunlock(_Vtmutex);
			return NIL(Vthread_t*);
		}

		if(_Vtnlist > 0)
		{	memcpy(list,_Vtlist,_Vtnlist*sizeof(Vthread_t*));
			free(_Vtlist);
		}

		_Vtlist = list;
		_Vtnlist += INCR;

		for(s = slot; s < _Vtnlist; ++s)
			list[s] = NIL(Vthread_t*);
	}

	if(!(v = vt) )
	{	if(!(v = (Vthread_t*)malloc(sizeof(Vthread_t))) )
		{	vtmtxunlock(_Vtmutex);
			return NIL(Vthread_t*);
		}
		flags |= VT_INIT|VT_FREE;
	}

	if(flags&VT_INIT)
	{	v->state = (flags&VT_FREE);
		v->stack = 0;
		v->error = 0;
		v->exit  = NIL(Void_t*);
#if !_WIN32
		if((s = pthread_attr_init(&v->attrs)) != 0)
			v->error = s;
#endif
	}

	_Vtlist[slot] = v;

	vtmtxunlock(_Vtmutex);

	return v;

#endif /*vt_threaded*/
}
