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