/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	<string.h>

extern "C" {
#include	"task.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"pri_level.h"
}

#include	"v/v.h"

extern "C" {
SYS_QUEUE v_queue;

void vq_event_task(TKEY);
void init_v_queue();
void * copy_event_arg(void * arg,int size);


void
init_v_queue()
{
	memset(&v_queue,0,sizeof(SYS_QUEUE));
	v_queue.flags = QF_FIFO;
	v_queue.key_func = vq_event_task;
	v_queue.pri = PRI_V_QUEUE;
	setup_queue(&v_queue);
}

void *
copy_event_arg(void * arg,int size)
{
void * ret;
	if ( arg == 0 )
		return 0;
	if ( size == 0 )
		return 0;
	ret = d_alloc(size);
	memcpy(ret,arg,size);
	return ret;
}

void
xx_vq_insert_callback(
		VObject *object,
		V_CALLBACK(handler),
		void *usr_arg,
		void *sys_arg,
		int sys_arg_size,
		char * __f,
		int __l)
{
VQueEventHandler * arg;
char buf[20];
	arg = (VQueEventHandler*)d_alloc(sizeof(*arg));
	memset(&arg->h,0,sizeof(arg->h));

	arg->object = object;
	arg->handler = handler;
	arg->usr_arg = usr_arg;
	arg->sys_arg_size = sys_arg_size;
	arg->sys_arg = sys_arg_size ? copy_event_arg(sys_arg,sys_arg_size) : 0;
	
	arg->__file = __f;
	arg->__line = __l;

	sprintf(buf,"key%p",object);
	arg->h.key = nl_copy_str(std_cm,buf);
	insert_queue(&v_queue,arg,0);
}

void
vq_event_task(TKEY d)
{
XL_INTERPRETER * xli;
L_CHAR * key;
SYS_QUEUE * que;
VQueEventHandler * arg;


	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);


	for ( ; ; ) {
		arg = (VQueEventHandler*)delete_queue(que,
				(int(*)())sq_key_cond,key,0);
		if ( arg == 0 )
			break;

		(*arg->handler)(arg->object,arg->usr_arg,arg->sys_arg);


		d_f_ree(arg->h.key);
		if ( arg->sys_arg )
			d_f_ree(arg->sys_arg);
		d_f_ree(arg);
	}


	release_qkey(que,key);
	d_f_ree(key);
	close_self_interpreter();
}

} // extern "C";
