package org.perl.inline.java ; import java.util.* ; import java.io.* ; /* Queue for callbacks to Perl... */ class InlineJavaCallbackQueue { // private InlineJavaServer ijs = InlineJavaServer.GetInstance() ; private ArrayList queue = new ArrayList() ; private boolean wait_interrupted = false ; private boolean stream_opened = false ; InlineJavaCallbackQueue(){ } synchronized void EnqueueCallback(InlineJavaCallback ijc){ queue.add(ijc) ; notify() ; } synchronized private InlineJavaCallback DequeueCallback(){ if (GetSize() > 0){ return (InlineJavaCallback)queue.remove(0) ; } return null ; } synchronized int WaitForCallback(double timeout){ long secs = (long)Math.floor(timeout) ; double rest = timeout - ((double)secs) ; long millis = (long)Math.floor(rest * 1000.0) ; rest = (rest * 1000.0) - ((double)millis) ; int nanos = (int)Math.floor(rest * 1000000.0) ; return WaitForCallback((secs * 1000) + millis, nanos) ; } /* Blocks up to the specified time for the next callback to arrive. Returns -1 if the wait was interrupted voluntarily, 0 on timeout or > 0 if a callback has arrived before the timeout expired. */ synchronized int WaitForCallback(long millis, int nanos){ wait_interrupted = false ; Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "waiting for callback request (" + millis + " millis, " + nanos + " nanos) in " + t.getName() + "...") ; if (! stream_opened){ return -1 ; } while ((stream_opened)&&(! wait_interrupted)&&(IsEmpty())){ try { wait(millis, nanos) ; // If we reach this code, it means the either we timed out // or that we were notify()ed. // In the former case, we must break out and return 0. // In the latter case, either the queue will not be empty or // wait_interrupted will be set. We must therefore also break out. break ; } catch (InterruptedException ie){ // Do nothing, return and wait() some more... } } InlineJavaUtils.debug(3, "waiting for callback request finished " + t.getName() + "...") ; if (wait_interrupted){ return -1 ; } else { return GetSize() ; } } /* Waits indefinetely for the next callback to arrive and executes it. Return true on success of false if the wait was interrupted voluntarily. */ synchronized boolean ProcessNextCallback() throws InlineJavaException, InlineJavaPerlException { int rc = WaitForCallback(0, 0) ; if (rc == -1){ // Wait was interrupted return false ; } // DequeueCallback can't return null because we explicetely // waited until a callback was there. Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "processing callback request in " + t.getName() + "...") ; InlineJavaCallback ijc = DequeueCallback() ; ijc.Process() ; ijc.NotifyOfResponse(t) ; return true ; } private boolean IsEmpty(){ return (GetSize() == 0) ; } void OpenCallbackStream(){ stream_opened = true ; } synchronized void CloseCallbackStream(){ stream_opened = false ; InterruptWaitForCallback() ; } boolean IsStreamOpen(){ return stream_opened ; } int GetSize(){ return queue.size() ; } synchronized private void InterruptWaitForCallback(){ Thread t = Thread.currentThread() ; InlineJavaUtils.debug(3, "interrupting wait for callback request in " + t.getName() + "...") ; wait_interrupted = true ; notify() ; } }