Headless Thread

The component will periodically poke the interpreter. It will alternately let run the interpreter in debug mode and trace mode. The diagram below shows the realized timing. The debug mode will only last 0.5ms. During debug mode the measured program will nearly run at full speed. On the other hand the trace mode will last as long as 2.0ms. During trace mode the measured program will run much slower since the custom hook is called and the counts are accumulated. We therefore give more time to the trace mode than to the debug mode.


We will only poke one interpreter. A design that pokes multiple interpreters would also be possible. For the sake of simplicity we only show the simple solution. The interpreter under consideration will be stored in a field of the headless thread. The main loop of the headless thread will then use the setStatus() method to change the debugger mode:

    try {
        inter.setStatus(
           CapabilityDevelopment.STATUS_SYS_TRACE_MODE, on);
    } catch (InterpreterMessage x) {
        throw new RuntimeException(x);
    }

The headless thread has then to sleep a given time. We opted for an implementation based on nano-seconds. Corresponding APIs are available since JDK 1.5 in connection with the new Java package java.util.concurrent. The thread will create a monitor via the class ReentrantLock and obtain a condition from it. The condition is then used to wait with a nano-second argument. Since a condition is allowed to yield for no reason we have implemented a loop that repeatedly waits:

    long sleep = SLEEP[on ? 1 : 0] –
                  (System.nanoTime() - lastTime);
    try {
        while (sleep > 0)
            sleep = cond.awaitNanos(sleep);
    } catch (InterruptedException x) {
        return;               
    }

The headless thread will not have any associated graphic element. We put it into the responsibility of the tester to manually start and stop the headless thread. To start the headless thread there will be a Java method that will return a handle to a newly created and started headless thread. We will store the handle in a thread local predicate. The corresponding Prolog code reads as follows:

    :- foreign(start_sampler/1, 'jekdev.study.ports.ThreadAPI',
    startSampler('Interpreter')).
    
    :- dynamic handle/1.
    
    start_sampler :-
      start_sampler(X),
      assertz(handle(X)).

The handle can later be retrieved to stop the thread again. There is a Java method for this purpose and corresponding Prolog code. More details can be found in the appendix where the full Java classes and Prolog text is listed.

Comments