/*
* javaIdle.c --
*
* This file contains the native methods for the IdleHandler class.
*
* Copyright (c) 1998 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: javaIdle.c,v 1.7 2006/07/26 20:55:27 mdejong Exp $
*/
#include "java.h"
#include "javaNative.h"
/*
* Static functions used in this file.
*/
static void JavaIdleProc(ClientData clientData);
/*
*----------------------------------------------------------------------
*
* Java_tcl_lang_IdleHandler_doWhenIdle --
*
* Create a C level idle handler for a Java IdleHandler object.
*
* Results:
* Retuns an address to be stored in clientData.
*
* Side effects:
* Will create a new global ref to this object.
*
*----------------------------------------------------------------------
*/
jlong JNICALL
Java_tcl_lang_IdleHandler_doWhenIdle(
JNIEnv *env, /* Java environment. */
jobject idle) /* Handle to IdleHandler object. */
{
jobject gref = (*env)->NewGlobalRef(env, idle);
/*
* It is not possible to store the global ref as an Object
* field because the garbage collector could move the
* object in memory before cancel was invoked. Instead,
* store it as a long.
*/
jlong clientData = 0;
*(jobject *)&clientData = gref;
/*
fprintf(stderr, "doWhenIdle idle instance is %x\n", idle);
fprintf(stderr, "doWhenIdle wrote long %llx\n", clientData);
fprintf(stderr, "doWhenIdle gref is %x\n", gref);
*/
Tcl_DoWhenIdle(JavaIdleProc, (ClientData) gref);
return clientData;
}
/*
*----------------------------------------------------------------------
*
* Java_tcl_lang_IdleHandler_cancelIdleCall --
*
* Delete a C level idle handler for a Java IdleHandler object.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void JNICALL
Java_tcl_lang_IdleHandler_cancelIdleCall(
JNIEnv *env, /* Java environment. */
jobject idle, /* Handle to IdleHandler object. */
jlong clientData) /* Ptr to global ref passed as client data */
{
jobject gref = *(jobject *)&clientData;
/*
fprintf(stderr, "cancelIdleCall idle instance is %x\n", idle);
fprintf(stderr, "cancelIdleCall read long %llx\n", clientData);
fprintf(stderr, "cancelIdleCall gref is %x\n", gref);
*/
Tcl_CancelIdleCall(JavaIdleProc, (ClientData) gref);
/*
* Free global ref so object can be garbage collected.
*/
(*env)->DeleteGlobalRef(env, gref);
}
/*
*----------------------------------------------------------------------
*
* JavaIdleProc --
*
* This function is called when a Java idle event occurs.
*
* Results:
* None.
*
* Side effects:
* Invokes arbitrary Java code.
*
*----------------------------------------------------------------------
*/
static void
JavaIdleProc(
ClientData clientData) /* Global IdleHandler reference */
{
JNIEnv *env = JavaGetEnv();
jobject exception;
jobject gref = (jobject) clientData;
JavaInfo* jcache = JavaGetCache();
int fromJNIMethod = JavaNotifierInDoOneEvent();
#ifdef TCLBLEND_DEBUG
fprintf(stderr, "TCLBLEND_DEBUG: JavaIdleProc : fromJNIMethod is %d\n", fromJNIMethod);
#endif /* TCLBLEND_DEBUG */
/*fprintf(stderr, "JavaIdleProc got global ref %x\n", gref);*/
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
Tcl_Panic("JavaIdleProc : unexpected pending exception");
}
/*
* Call IdleHandler.invoke(). If an exception was raised and
* this method was invoked as a result of a Notifier.doOneEvent
* then propagate the exception. If this method was
* called from Tcl, then just print the error since we can't
* leave the exception pending.
*/
(*env)->CallVoidMethod(env, gref, jcache->invokeIdle);
exception = (*env)->ExceptionOccurred(env);
if (exception) {
if (!fromJNIMethod) {
fprintf(stderr, "Java Exception in JavaIdleProc (Tcl_DoWhenIdle handler)\n");
(*env)->ExceptionDescribe(env);
}
(*env)->ExceptionClear(env);
}
/*
* Free global ref so object can be garbage collected.
*/
(*env)->DeleteGlobalRef(env, gref);
/*
* Rethrow the exception.
*/
if (exception) {
if (fromJNIMethod) {
#ifdef TCLBLEND_DEBUG
fprintf(stderr, "TCLBLEND_DEBUG: JavaIdleProc : rethrowing Exception\n");
#endif /* TCLBLEND_DEBUG */
(*env)->Throw(env, exception);
}
(*env)->DeleteLocalRef(env, exception);
}
}