org.vishia.java2C.test
Class TestThread

java.lang.Object
  extended by org.vishia.java2C.test.TestThread
All Implemented Interfaces:
java.lang.Runnable

public class TestThread
extends java.lang.Object
implements java.lang.Runnable

This class demonstrates and tests the usage of threads with the synchronized access to data (mutex). It implements the run()-Method of the Thread defined in the interface Runnable.

The threads private data which should be able to access only by the current thread are stored in an extra class, here defined as static inner class.


Nested Class Summary
private static class TestThread.TestThreadLocalData
          This class is defined only to use in the threads context.
 
Field Summary
private  int testCt1
          Two test counter, they will be count always simultaneously.
private  int testCt2
          Two test counter, they will be count always simultaneously.
(package private)  int testCtInterrupted
          This counter is used to test whether the interrupting of the thread works.
private  TestWaitNotify.WaitNotifyData theNotifyingData
          Aggregation to data to check wait/notify.
(package private)  java.lang.Thread theThread
          A Thread-instance is a composite part of this class.
private  boolean threadFinished
          This is a central thread-control variable.
private  boolean threadRunning
          This is a central thread-control variable.
 
Constructor Summary
TestThread(TestWaitNotify.WaitNotifyData theNotifyingData)
          Constructor.
 
Method Summary
 boolean isThreadFinished()
          Returns true if the class private variable threadFinished is set.
 void otherThreadRoutine()
          This routine is called from outside in another thread.
 void run()
          This is the thread main-routine complying the Java rules.
 void start()
          Facade routine to start the Thread.
(package private)  void testSynchronized(TestThread.TestThreadLocalData threadLocalData)
          This routine shows and support test of a mutex-access.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

threadRunning

private boolean threadRunning
This is a central thread-control variable. If it is set to true, if the thread is started.


threadFinished

private boolean threadFinished
This is a central thread-control variable. If it is set to false, if the thread is finished.


testCt1

private int testCt1
Two test counter, they will be count always simultaneously. Therefore a synchronized is used. The data of an instance of this class, especially this counters are visible from outside the thread. Because there are private, an access to it is only possible in this class. But the method which is accessing may be called from another thread. Therefore a mutex-access is necessary, see testSynchronized(org.vishia.java2C.test.TestThread.TestThreadLocalData) and otherThreadRoutine().


testCt2

private int testCt2
Two test counter, they will be count always simultaneously. Therefore a synchronized is used. The data of an instance of this class, especially this counters are visible from outside the thread. Because there are private, an access to it is only possible in this class. But the method which is accessing may be called from another thread. Therefore a mutex-access is necessary, see testSynchronized(org.vishia.java2C.test.TestThread.TestThreadLocalData) and otherThreadRoutine().


testCtInterrupted

int testCtInterrupted
This counter is used to test whether the interrupting of the thread works.


theThread

final java.lang.Thread theThread
A Thread-instance is a composite part of this class. The thread-instance organizes the thread only. Another possibility is deriving this class from Thread instead implementing Runnable. It is realized in TestWaitNotify.


theNotifyingData

private final TestWaitNotify.WaitNotifyData theNotifyingData
Aggregation to data to check wait/notify.

Constructor Detail

TestThread

TestThread(TestWaitNotify.WaitNotifyData theNotifyingData)
Constructor.

Parameters:
theNotifyingData - The aggregation to data, which is used to test wait-notify.
Method Detail

run

public void run()
This is the thread main-routine complying the Java rules. The routine is started if the java.lang.Thread-instance, which associates the class (theThread, is called with ,,start(),,-method. implements Runnable.run()

The thread-main-routine creates instances, which are only accessed by this thread. In Java the instances are referenced, but the reference is only known in stack context, provided to called routines via parameter. In C the instances are allocated in the stack because a @ java2c=stackInstance. is written thereby. Large-size instances need an adequate stack size. The Java-code for this code-snippet is:
     ...* @java2c=stackInstance. * /
    TestThreadLocalData threadLocalData = new TestThreadLocalData();
 
The generated C-code is:
    TestThread_Test__TestThreadLocalData_s threadLocalData;  
    ...
    init_ObjectJc(&(threadLocalData.base.object), sizeof(threadLocalData), 0); 
    ctorO_TestThread_Test__TestThreadLocalData(&(threadLocalData.base.object), _thCxt);
 
The thread contains a for-loop to force a determined call of testSynchronized, and a call of notify(...) to test the wait/notify-concept with a third thread. Than a sleep is called to delay the execution of the thread with deterministic milliseconds-time. The Java-form is:
    for(int liveCt = 0; liveCt <200; liveCt++){
      testSynchronized(threadLocalData);
      theNotifyingData.notify(testCt1);
      try{ Thread.sleep(10); } 
      catch(InterruptedException exc){
        testCtInterrupted +=1;
      }

    }//for
 
The catch clause is processed if the thread was woken up abnormal. The coding of this catch is prescribed in Java. In C it is mapped too, but it isn't used yet.

The C-code of this snippet is:
      for(liveCt = 0; liveCt < 200; liveCt++)
        { testSynchronized_TestThread_Test(ythis, & (threadLocalData), _thCxt);
          theNotifyingDataMtbl.mtbl->notify( (theNotifyingDataMtbl.ref), ythis->testCt1, _thCxt);
          TRY
          { sleep_ThreadJc(10, _thCxt);
          }_TRY
          CATCH(InterruptedException, exc)
            { ythis->testCtInterrupted += 1;
            }
          END_TRY
        }
 
The call of theNotifyingDataMtbl.mtbl->notify(...) is executed dynamically, because the destination instance can be an derived class of the reference type in an enhancement of the example. To prevent effort to get the method table reference, the Java-code contains a stack-local reference at top of the routine, see Docu.D_SuperClassesAndInterfaces.D6_callingOverrideableMethods().
    /**Use local variable to enforce only one preparation of the method table for dynamic call:

Specified by:
run in interface java.lang.Runnable

testSynchronized

final void testSynchronized(TestThread.TestThreadLocalData threadLocalData)
This routine shows and support test of a mutex-access. The testCt1 and testCt2 of this class are decremented together. The rule is: both counter should contain the same number. There are incremented in the routine otherThreadRoutine() from another thread and decremented here independently, but similar. The equality of both counter values are tested on entry using an assert statement. The Java-Code is
    synchronized(this)
    { assert(testCt1 == testCt2);
      testCt1 -=2;
      try{ Thread.sleep(5);} 
      catch (InterruptedException e){}   
      testCt2 -=2;
      threadLocalData.x = testCt1;
    }  
 
The C-Code is:
    synchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object)); {
      { ASSERT(ythis->testCt1 == ythis->testCt2);
        ythis->testCt1 -= 2;
        TRY
        { sleep_ThreadJc(5, _thCxt);
        }_TRY
        CATCH(InterruptedException, e){} END_TRY
        ythis->testCt2 -= 2;
        threadLocalData->x = ((float)(ythis->testCt1));
      }
    } endSynchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object));
 
The sleep-call is disposed here only to provoke a thread switch during this mutex-saved operation. Without synchronized the interruption of this statement block between the two counter-increments from the other thread accessing the counters is likely, the synchronized is effective well able to test.

The Java construction
 synchronized {
   ...guarded block
 }  
 
 is well bounded with { .... }, the programmer can't forget the exit from the guard.
 It is the syntax of Java. Hand written in C, the exit of the guard block (critical section)
 may be missed because the programmer has forgotten it. The C-translation of Java is safety respectively this problem,
 though an extra routine endSynchronized_ObjectJc is called.

Parameters:
threadLocalData -

start

public void start()
Facade routine to start the Thread. The Java-lines are:
    / **@java2c=stackSize(TestThreadLocalData+2000). * /
    theThread.start();
 
The stackSize is necessary for the C-implementation. Because an instance of TestThreadLocalData is created in the run()-Method, its size should be regarded. The rest, 2000 Bytes, is a proper value for typical stack usages.

The translated C-code is
    start_ThreadJc(& (ythis->theThread)
                  , sizeof(TestThread_Test__TestThreadLocalData_s)+2000, _thCxt);
 
The stackSize-annotation is translated to the stackSize-parameter-value for the start_ThreadJc-routine. The really size should be tested at C-level-debugging.


otherThreadRoutine

public void otherThreadRoutine()
This routine is called from outside in another thread. It demonstrates a concurrent access which is guard with a synchronized adequate to run(). This routine works with 500 loops in a time of 10 ms. At its end #shouldRun is set to false, which causes an aborting of the run()-routine and therefore the finishing of the thread.


isThreadFinished

public final boolean isThreadFinished()
Returns true if the class private variable threadFinished is set. That occurs at last action of the run()-routine of the thread.

Returns: