/**********************************************************************
 
	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	<stdlib.h>
#include	"memory_debug.h"
#include	"memory_routine.h"
#include	"task.h"
#include	"xl.h"

void gc_gb_sexp();
extern SEM fifo_lock;

void
gc_xl_fifo(XL_FIFO * f)
{
	for ( ; f ; f = f->next )
		gc_gb_sexp(f->cmd);
}

void
put_xl_fifo(XL_INTERPRETER * xli,XL_SEXP * cmd)
{
XL_FIFO * f;
	lock_task(fifo_lock);
	if ( xli->mode != XIM_RUN )
		goto end;
	f = d_alloc(sizeof(*f));
	f->next = 0;
	f->cmd = cmd;
	if ( xli->fifo_head == 0 )
		xli->fifo_head = xli->fifo_tail = f;
	else {
		xli->fifo_tail->next = f;
		xli->fifo_tail = f;
	}
	wakeup_task((int)&xli->fifo_head);
end:
	unlock_task(fifo_lock,"put_xl_fifo");
}

XL_SEXP *
get_xl_fifo(XL_INTERPRETER * xli,int flag)
{
XL_FIFO * f;
XL_SEXP * ret;

retry:
	lock_task(fifo_lock);
	if ( xli->mode != XIM_RUN )
		ret = 0;
	else if ( xli->fifo_head ) {
		lock_mem();
		f = xli->fifo_head;
		xli->fifo_head = f->next;
		if ( xli->fifo_head == 0 )
			xli->fifo_tail = 0;
		ret = f->cmd;
		gc_set_nl(ret,gc_gb_sexp);
		unlock_mem();
		d_f_ree(f);
	}
	else if ( xli->mode == XIM_RUN && flag == XFF_BLOCK ) {
		sleep_task((int)&xli->fifo_head,fifo_lock);
		goto retry;
	}
	else	ret = 0;
	unlock_task(fifo_lock,"get_xl_fifo");
	return ret;
}

int
check_fifo(XL_INTERPRETER * xli)
{
int ret;
	lock_task(fifo_lock);
	if ( xli->fifo_head )
		ret = 1;
	else	ret = 0;
	unlock_task(fifo_lock,"check_fifo");
	return ret;
}

void
interrupt_fifo(XL_INTERPRETER * xli)
{
	lock_task(fifo_lock);
	wakeup_task((int)&xli->fifo_head);
	unlock_task(fifo_lock,"interrupt_fifo");
}

void
close_fifo(XL_INTERPRETER * xli)
{
XL_FIFO * f;
	lock_task(fifo_lock); 
	for ( ; xli->fifo_head ; ) {
		f = xli->fifo_head;
		xli->fifo_head = f->next;
		d_f_ree(f);
	}
	xli->fifo_tail = 0;
	unlock_task(fifo_lock,"close_fifo");
}
