/*
 * sGCfinalize.c -- dummy implementation of PCedar finalization.
 *  taken from Mike Agostino's pseudo PCR.
 *  spcr has finalization available, but the PCedar interface relies
 *  on multiple threads, and thus can't really be implememnted.
 *
 *  Hans-J. Boehm 	January 25, 1993 12:48:56 pm PST
 */
#include <xr/GC.h>
#include <xr/sMisc.h>

XR←FinalizationHandle GC←finalizeListHead;

static void
XR←RemoveFromFQInternal();

XR←FinalizationState
XR←DisableFinalization(h)
XR←FinalizationHandle h;
{
    XR←FinalizationHandle p, prev;
    XR←FinalizationState q;
    word w;

    if( h == NIL ) return fzsDisabled;

    if( h->associatedFQ == NIL ) {
	q = fzsDisabled;
    } else if( !XR←IsDisguised(h) ) {
	q = fzsOnFQ;
	XR←RemoveFromFQInternal(h);
    } else {
	q = fzsEnabled;
	p = GC←finalizeListHead;
	prev = NIL;
	for(;;) {
	    if( p == NIL ) break;
	    if( p == h ) {
		if( prev == NIL )
		    GC←finalizeListHead = p->next;
		else
		    prev->next = p->next;
		break;
	    }
	    prev = p;
	    p = p->next;
	}
	w = XR←FetchFromDisguised(h);
	XR←StoreUndisguised(w,h);
	h->associatedFQ = NIL;
    }
    h->next = NIL;
    return q;
}

XR←FinalizationState
XR←ReenableFinalization(h, fq)
XR←FinalizationHandle h;
XR←FinalizationQueue fq;
{
   XR←FinalizationState q;
   word object;
    
   if( (h == NIL) || (fq == NIL) ) return fzsDisabled;
	
   if( XR←IsDisguised(h) ) {
	q = fzsEnabled;
   } else {
	if( h->associatedFQ == NIL ) {
	    q = fzsDisabled;
	} else {
	    q = fzsOnFQ;
	    XR←RemoveFromFQInternal(h);
	}
	object = XR←FetchFromUndisguised(h);
	XR←StoreDisguised(object,h);
	h->next = GC←finalizeListHead;
	GC←finalizeListHead = h;
    }
    h->associatedFQ = fq;
    return q;
}

void
XR←EnableFinalization(object, fq, h)
XR←Pointer object;
XR←FinalizationQueue fq;
XR←FinalizationHandle h;
{
	if (object == NIL || fq == NIL ||  h == NIL) return;
	
	XR←StoreDisguised(object, h);
	h->associatedFQ = fq;
	h->next = GC←finalizeListHead;
	GC←finalizeListHead = h;
}

bool
XR←FQEmpty(fq)
XR←FinalizationQueue fq;
{
        return fq == NIL || fq->head == NIL;
}

XR←FinalizationHandle
XR←FQNextNoAbort(fq)
XR←FinalizationQueue fq;
{
	SPCR←NotImplemented("XR←FQNextNoAbort");
}

XR←FinalizationState
XR←GetFinalizationState(h)
XR←FinalizationHandle h;
{
	XR←FinalizationState q;
	
	if( h == NIL ) return fzsDisabled;
	
	if( XR←IsDisguised(h) ) {
	    q = fzsEnabled;
        } else if( h->associatedFQ != NIL ) {
	    q = fzsOnFQ;
        } else {
	    q = fzsDisabled;
        }
        return q;
}

XR←Pointer
XR←HandleToObject(h)
XR←FinalizationHandle h;
{
	word w;
	if (h == NIL) return NIL;
	
	if( XR←IsDisguised(h) ) {
	   w = XR←FetchFromDisguised(h);
	} else {
	   w = XR←FetchFromUndisguised(h);
	}
	return (XR←Pointer)w;
}

XR←FinalizationQueue
XR←NewFQ() {
	XR←FinalizationQueue fq;

	fq = (XR←FinalizationQueue)
	      GC←malloc(sizeof(struct XR←FinalizationQueueStructure));
	fq->head = NIL;
	fq->tail = NIL;
	return fq;
}

XR←FinalizationHandle
XR←NewFinalizationHandle() {
	XR←FinalizationHandle h = (XR←FinalizationHandle)
           GC←malloc(sizeof(struct XR←FinalizableObjectStructure));
	h->firstword = 0;
	h->secondword = 0;
	h->associatedFQ = NIL;
	h->next = NIL;
	return h;
}

static void
XR←RemoveFromFQInternal (h)
    XR←FinalizationHandle h;
{
    XR←FinalizationQueue fq;
    XR←FinalizationHandle p, prev;

    fq = h->associatedFQ;
    p = fq->head;
    prev = NIL;
    for(;;) {
	if( p == h ) {
	    if( prev == NIL ) fq->head = p->next; else prev->next = p->next;
	    if( fq->tail == p ) fq->tail = prev;
	    p->next = NIL;
	    p->associatedFQ = NIL;
	    break;
	}
	if( p == NIL ) XR←Panic("RemoveFromFQInternal 0");
	prev = p;
	p = p->next;
    }
}