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 }