001    package org.vishia.java2C.test;
002    
003    /**This class demonstrates and tests the usage of threads with the synchronized access to data (mutex). 
004     * It implements the run()-Method of the Thread defined in the interface Runnable. 
005     * <br><br>
006     * The threads private data which should be able to access only by the current thread are stored
007     * in an extra class, here defined as static inner class.
008     *
009     */
010    public class TestThread implements Runnable
011    {
012      
013      /**This is a central thread-control variable. If it is set to true, if the thread is started. */
014      private boolean threadRunning;
015      
016      /**This is a central thread-control variable. If it is set to false, if the thread is finished. */
017      private boolean threadFinished;
018      
019      /**Two test counter, they will be count always simultaneously. Therefore a <code>synchronized</code>
020       * is used. The data of an instance of this class, especially this counters are visible from outside the thread.
021       * Because there are private, an access to it is only possible in this class. But the method which is accessing
022       * may be called from another thread. Therefore a mutex-access is necessary, 
023       * see {@link #testSynchronized(org.vishia.java2C.test.TestThread.TestThreadLocalData)}
024       * and {@link #otherThreadRoutine()}.
025       * 
026       */
027      private int testCt1 = 0, testCt2 = 0;
028      
029      /**This counter is used to test whether the interrupting of the thread works. */
030      int testCtInterrupted = 0;
031      
032      /**A Thread-instance is a composite part of this class. The thread-instance organizes the thread only.
033       * Another possibility is deriving this class from Thread instead implementing Runnable. It is realized
034       * in {@link TestWaitNotify}. 
035       */
036      final Thread theThread = new Thread(this, "TestThread");
037      
038      /**This class is defined only to use in the threads context. No other thread should have access to it.
039       * Therefore the instance can be defined in a thread-local data range. For Java2C it is possible
040       * to create a stack-instance. It is done in the {@link TestThread#run()}. routine.
041       * <br><br>
042       * 
043       */
044      private final static class TestThreadLocalData
045      {
046        float x,y;
047        
048        /**Example for a large data area. The buffer is allocated in C in the class as embedded instance,
049         * because the class' instances is allocated in stack, the buffer is located in the stack.
050         * <br><br>
051         * If the Java program takes the reference of the buffer and stores it in another instance,
052         * which is accessed from another thread, it is possible in Java because in Standard-Java
053         * it's a normal instance in heap. But the implementation in C in a protected memory system
054         * will force a memory protection error, because the data area is located in the stack of another thread.
055         * The stacks of several threads should not accessible one to another. That is ones of distinctions
056         * between a standard Java environment to test and the implementation in a target system.
057         * Such errors should recognized in the test of target. 
058         */
059        final StringBuffer threadownBuffer = new StringBuffer(3000);
060      }
061      
062      /**Aggregation to data to check wait/notify. */
063      private final TestWaitNotify.WaitNotifyData theNotifyingData;
064      
065      /**Constructor. 
066       * @param theNotifyingData The aggregation to data, which is used to test wait-notify.
067       */
068      TestThread(TestWaitNotify.WaitNotifyData theNotifyingData)
069      {
070        this.theNotifyingData = theNotifyingData;
071      }
072      
073      /**This is the thread main-routine complying the Java rules. The routine is started 
074       * if the java.lang.Thread-instance, which associates the class ({@link #theThread}, 
075       * is called with ,,start(),,-method. 
076       * implements {@link java.lang.Runnable#run()}
077       * <br><br>
078       * The thread-main-routine creates instances, which are only accessed by this thread.
079       * In Java the instances are referenced, but the reference is only known in stack context,
080       * provided to called routines via parameter. In C the instances are allocated in the stack
081       * because a <code>@ java2c=stackInstance.</code> is written thereby. Large-size instances need
082       * an adequate stack size. The Java-code for this code-snippet is:
083       * <pre class="Java">
084         ...* @java2c=stackInstance. * /
085        TestThreadLocalData threadLocalData = new TestThreadLocalData();
086       * </pre>
087       * The generated C-code is:
088       * <pre class="CCode">
089        TestThread_Test__TestThreadLocalData_s threadLocalData;  
090        ...
091        init_ObjectJc(&(threadLocalData.base.object), sizeof(threadLocalData), 0); 
092        ctorO_TestThread_Test__TestThreadLocalData(&(threadLocalData.base.object), _thCxt);
093       * </pre>
094       * The thread contains a <code>for</code>-loop to force a determined call  of <code>testSynchronized</code>,
095       * and a call of <code>notify(...)</code> to test the wait/notify-concept with a third thread.
096       * Than a sleep is called to delay the execution of the thread with deterministic milliseconds-time. 
097       * The Java-form is:
098       * <pre class="Java">
099        for(int liveCt = 0; liveCt <200; liveCt++){
100          testSynchronized(threadLocalData);
101          theNotifyingData.notify(testCt1);
102          try{ Thread.sleep(10); } 
103          catch(InterruptedException exc){
104            testCtInterrupted +=1;
105          }
106          
107        }//for
108       * </pre>
109       * The catch clause is processed if the thread was woken up abnormal. The coding of this catch is prescribed in Java.
110       * In C it is mapped too, but it isn't used yet. 
111       * <br><br>
112       * The C-code of this snippet is:
113       * <pre class="CCode">
114          for(liveCt = 0; liveCt < 200; liveCt++)
115            { testSynchronized_TestThread_Test(ythis, & (threadLocalData), _thCxt);
116              theNotifyingDataMtbl.mtbl->notify( (theNotifyingDataMtbl.ref), ythis->testCt1, _thCxt);
117              TRY
118              { sleep_ThreadJc(10, _thCxt);
119              }_TRY
120              CATCH(InterruptedException, exc)
121                { ythis->testCtInterrupted += 1;
122                }
123              END_TRY
124            }
125       * </pre>
126       * The call of <code>theNotifyingDataMtbl.mtbl->notify(...)</code> is executed dynamically,
127       * because the destination instance can be an derived class of the reference type
128       * in an enhancement of the example. To prevent effort to get the method table reference,
129       * the Java-code contains a stack-local reference at top of the routine, 
130       * see {@link org.vishia.java2C.Docu.D_SuperClassesAndInterfaces#D6_callingOverrideableMethods()}.
131       * <pre class="Java">
132        /**Use local variable to enforce only one preparation of the method table for dynamic call:
133         * @java2c=dynamic-call.
134         * /
135        final TestWaitNotify.WaitNotifyData theNotifyingDataMtbl = theNotifyingData;
136       * </pre> 
137       */
138      public void run(){
139        threadRunning = true;
140        /**Use local variable to enforce only one preparation of the method table for dynamic call:
141         * @java2c=dynamic-call.
142         */
143        final TestWaitNotify.WaitNotifyData theNotifyingDataMtbl = theNotifyingData;
144        /**This instance is only visible in the threads context. It is allocated in the stack.
145         * @java2c=stackInstance. */
146        TestThreadLocalData threadLocalData = new TestThreadLocalData();
147        for(int liveCt = 0; liveCt <200; liveCt++){
148          testSynchronized(threadLocalData);
149          theNotifyingDataMtbl.notify(testCt1);
150          try{ Thread.sleep(10); } 
151          catch(InterruptedException exc){
152            testCtInterrupted +=1;
153          }
154          
155        }//for
156        System.out.println("test-thread stopped at " + threadLocalData.x);
157        threadFinished = true;
158      }
159    
160    
161      
162      /**This routine shows and support test of a mutex-access. 
163       * The {@link #testCt1} and {@link #testCt2} of this class are decremented together. 
164       * The rule is: both counter should contain the same number. There are incremented 
165       * in the routine {@link #otherThreadRoutine()} from another thread and decremented here
166       * independently, but similar. The equality of both counter values are tested on entry 
167       * using an assert statement. The Java-Code is
168       * <pre class="Java">
169        synchronized(this)
170        { assert(testCt1 == testCt2);
171          testCt1 -=2;
172          try{ Thread.sleep(5);} 
173          catch (InterruptedException e){}   
174          testCt2 -=2;
175          threadLocalData.x = testCt1;
176        }  
177       * </pre> 
178       * The C-Code is:
179       * <pre class="CCode">
180        synchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object)); {
181          { ASSERT(ythis->testCt1 == ythis->testCt2);
182            ythis->testCt1 -= 2;
183            TRY
184            { sleep_ThreadJc(5, _thCxt);
185            }_TRY
186            CATCH(InterruptedException, e){} END_TRY
187            ythis->testCt2 -= 2;
188            threadLocalData->x = ((float)(ythis->testCt1));
189          }
190        } endSynchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object));
191       * </pre>
192       * The <code>sleep</code>-call is disposed here only to provoke a thread switch 
193       * during this mutex-saved operation. Without <code>synchronized</code> the interruption of this
194       * statement block between the two counter-increments from the other thread accessing the counters
195       * is likely, the <code>synchronized</code> is effective well able to test.
196       * <br><br>
197       * The Java construction 
198       * <pre class="Java">
199       * synchronized {
200       *   ...guarded block
201       * }  
202       * <pre>
203       * is well bounded with <code>{ .... }</code>, the programmer can't forget the exit from the guard.
204       * It is the syntax of Java. Hand written in C, the exit of the guard block (critical section)
205       * may be missed because the programmer has forgotten it. The C-translation of Java is safety respectively this problem,
206       * though an extra routine <code>endSynchronized_ObjectJc</code> is called.
207       * @param threadLocalData
208       */
209      final void testSynchronized(TestThreadLocalData threadLocalData)
210      { synchronized(this)
211        { assert(testCt1 == testCt2);
212          testCt1 -=2;
213          
214          /**Let the thread sleeping to provoke a switch to the other thread. 
215           * It isn't a pattern for a well programming, because it is in a synchronized block.
216           * It is only prober to force errors.
217           */
218          try{ Thread.sleep(5);} 
219          catch (InterruptedException e){}   
220          testCt2 -=2;
221          threadLocalData.x = (float)testCt1;
222        }
223      }
224      
225      
226      
227      
228      /**Facade routine to start the Thread.
229       * The Java-lines are:
230       * <pre class="Java">
231        / **@java2c=stackSize(TestThreadLocalData+2000). * /
232        theThread.start();
233       * </pre>
234       * The stackSize is necessary for the C-implementation. Because an instance of <code>TestThreadLocalData</code>
235       * is created in the {@link #run()}-Method, its size should be regarded. 
236       * The rest, 2000 Bytes, is a proper value for typical stack usages.
237       * <br><br>
238       * The translated C-code is
239       * <pre class="CCode">
240        start_ThreadJc(& (ythis->theThread)
241                      , sizeof(TestThread_Test__TestThreadLocalData_s)+2000, _thCxt);
242       * </pre> 
243       * The stackSize-annotation is translated to the stackSize-parameter-value for the <code>start_ThreadJc</code>-routine.
244       * The really size should be tested at C-level-debugging.
245       */
246      public void start()
247      { /**@java2c=stackSize(TestThreadLocalData+2000). */
248        theThread.start();
249      }
250      
251      /**This routine is called from outside in another thread. It demonstrates a concurrent access 
252       * which is guard with a <code>synchronized</code> adequate to {@link #run()}.
253       * This routine works with 500 loops in a time of 10 ms. At its end {@link #shouldRun} is set to <code>false</code>,
254       * which causes an aborting of the {@link #run()}-routine and therefore the finishing of the thread.
255       * 
256       */
257      public void otherThreadRoutine()
258      {
259        for(int i = 0; i < 200; i++){
260          synchronized(this)
261          //if(testCt1 ==5){}
262          { assert(testCt1 == testCt2);
263            testCt1 +=3;
264            testCt2 +=3;
265          }
266          try{ Thread.sleep(10);} 
267          catch (InterruptedException e){}
268        }//for
269        
270        /**Wait unil the thread of the instance is finished: */
271        int ctWaitFinished = 0;
272        while(!isThreadFinished()){
273          ctWaitFinished ++;
274          /**This is a polling loop. It should be contain a reasonable wait statement to release the CPU-ressource while polling: */
275          try{ Thread.sleep(5);} 
276          catch (InterruptedException e){}
277        }
278        System.out.println("main-thread stopped at " + testCt1 + ", ctWaitFinished=" + ctWaitFinished);
279    
280      }
281    
282      /**Returns true if the class private variable {@link #threadFinished} is set. That occurs at last action
283       * of the {@link #run()}-routine of the thread.
284       * @return
285       */
286      public final boolean isThreadFinished()
287      {
288        return threadFinished;
289      }
290    }