001    package org.vishia.java2C.test;
002    
003    /**This class demonstrates and tests the usage of threads with wait and notify. 
004     * It implements the run()-Method of the Thread defined in the interface Runnable, which is inherited from the super class Thread.
005     * The class based on Thread, therefore no other instance is necessary to organize the thread. 
006     * <br><br>
007     * The threads private data which should be able to access only by the current thread are stored
008     * in an extra class, here defined as static inner class.
009     *
010     */
011    public class TestWaitNotify extends Thread
012    {
013    
014      /**This is a central thread-control variable. If it is set to false, the thread should finish. */
015      boolean shouldRun = true;
016      
017      //TODO if this class is placed after TestThreadLocalData, a translation error occurs. Test!
018      /**This class is visible from outside, it is used from the notifying thread and from this thread, 
019       * which waits for data.
020       * 
021       */
022      public final static class WaitNotifyData
023      {
024        /**A value which is supplied with notify. */
025        int x;
026        
027        /**Sequence counter to detect a notify. It is incremented on any notify(). */
028        int ctNewData;
029        
030        /**Notify routine, it may be called from outside. New data are stored than. The <code>notify()</code>-call
031         * have to be placed in a <code>synchronized</code>- (mutex-)-block. Elsewhere in Java an exception is thrown.
032         * It is necessary to do so. That <code>synchronized</code>-block should be used to set the data,
033         * which are supplied with the notify action. Than the data and the notify-call are mutual exclusive handled.
034         * The Java-code is: 
035         * <pre class="Java">
036          synchronized(this){
037            x = value;
038            ctNewData +=1;
039            notify();
040          }  
041         * </pre>
042         * The value is stored. The sequence counter is incremented to advertise the notify. Than notify is called.
043         * All this operations are done under mutex in the <code>synchronized</code>-block.
044         * The translated C-code is:
045         * <pre class="CCode">
046        synchronized_ObjectJc(& ((* (ythis)).base.object)); {
047          ythis->x = value;
048          ythis->ctNewData += 1;
049          notify_ObjectJc(& ((* (ythis)).base.object), _thCxt);
050        } endSynchronized_ObjectJc(& ((* (ythis)).base.object));
051         * </pre>
052         * @param value The value supplied with notify.
053         */
054        public void notify(int value)
055        { synchronized(this){
056            x = value;
057            ctNewData +=1;
058            notify();
059          }  
060        }
061      }
062      
063      
064      
065      
066      /**This class is defined only to use in the threads context. No other thread should have access to it.
067       * Therefore the instance can be defined in a thread-local data range. For Java2C it is possible
068       * to create a stack-instance.
069       * <br><br>
070       * 
071       */
072      private final static class TestThreadLocalData
073      {
074        int x,y;
075        
076        /**A sequence counter which holds the last value of {@link WaitNotifyData#ctNewData} to check
077         * whether all data are got.
078         * 
079         */
080        int seqCtLast = -1, seqCt;
081        
082        /**This counter is used to test whether the interrupting of the thread works. */
083        int testCtInterrupted = 0;
084        
085        int testCtNothingReceived = 0;
086        
087        int testCtSuccessNotify = 0;
088        
089        int testCtMissNotify = 0;
090        
091        /**Association to the data which are notifying from outside.
092         */
093        private final WaitNotifyData theAwaitingData;
094    
095        TestThreadLocalData(WaitNotifyData theAwaitingDataP)
096        { this.theAwaitingData = theAwaitingDataP;  ///
097        }
098        
099        /**In this routine the thread is waiting for data. The thread runs only, if new data are available.
100         * But such an thread may be blocked forever, if no notifying occurs. Therefore it may be recommended,
101         * that the wait action is interrupted cyclically, to check some other conditions. In this case this
102         * routine waits max 1 second. If a notify doesn't occur, it returns anyway 
103         * because outside there may be some other things to work.
104         * <br><br>
105         * The core of the routine is a wait for new data in Java written as:
106         * <pre class="Java">
107            synchronized(theAwaitingData){
108              if(seqCtLast == -1){
109                seqCt = seqCtLast = theAwaitingData.ctNewData;
110              }
111              theAwaitingData.wait(1000);
112              seqCt = theAwaitingData.ctNewData;  //same as seqCtLast if no notify is called.
113              valueFromAwaitingData = theAwaitingData.x;  
114            }  
115         * </pre>
116         * This is translated to C in form:
117         * <pre class="CCode">
118          synchronized_ObjectJc(& ((* (REFJc(ythis->theAwaitingData))).base.object)); {
119            if(ythis->seqCtLast == -1) 
120            { 
121              ythis->seqCt = ythis->seqCtLast = REFJc(ythis->theAwaitingData)->ctNewData;
122            }
123            wait_ObjectJc(& ((*(REFJc(ythis->theAwaitingData))).base.object), 1000, _thCxt);
124            ythis->seqCt = REFJc(ythis->theAwaitingData)->ctNewData;
125            valueFromAwaitingData = REFJc(ythis->theAwaitingData)->x;
126          } endSynchronized_ObjectJc(& ((* (REFJc(ythis->theAwaitingData))).base.object));
127         * </pre>
128         * The rest of code tests the seqCt. If new data are available, the seqCt is incremented for 1.
129         * If a notify is missed, the counter is incremented for greater 1. If no notify is occured,
130         * but the wait time is out, the seqCt isn't incremented. This three conditions are tested, 
131         * and the appropriate counters are counted. The counters give an overview of occurrence 
132         * while running the process. Last not least the value given by notify is processed. But it is
133         * only an example.
134         */
135        private void awaitData()
136        {
137          int valueFromAwaitingData;
138          try { 
139            synchronized(theAwaitingData){
140              if(seqCtLast == -1){
141                /**initial:*/
142                seqCt = seqCtLast = theAwaitingData.ctNewData;
143              }
144              /**Wait at maximum 1 second. */
145              theAwaitingData.wait(1000);
146              /**the thread is waken up either because notify or because time.*/
147              seqCt = theAwaitingData.ctNewData;  //same as seqCtLast if no notify is called.
148              /**Copy the value to a stack variable, because after synchronized-end the value may be changed already.*/
149              valueFromAwaitingData = theAwaitingData.x;  
150            }  
151          } 
152          catch(InterruptedException exc){
153            testCtInterrupted +=1;
154            valueFromAwaitingData = 0;
155          }
156          /**All data to process are stored in this instance, it is accessible only be the own thread. */
157          int seqCtDiff = seqCt - seqCtLast;
158          seqCtLast = seqCt;
159          if(seqCtDiff == 1){
160            /**The next data are received.*/
161            x += valueFromAwaitingData;
162            testCtSuccessNotify +=1;
163          }
164          else if(seqCtDiff == 0){
165            /**A wake up because time cycle has occurred ; */
166            testCtNothingReceived +=1;
167          }
168          else if(seqCtDiff > 0){
169            testCtMissNotify +=1;
170          }
171          else {
172            assert(false);
173          }
174        }
175        
176        
177        
178      }
179      
180      
181      /**Aggregation to data to check wait/notify. */
182      final WaitNotifyData theAwaitingData;
183      
184      
185      /**Constructor. 
186       * @param theAwaitingData for aggregation
187       */
188      TestWaitNotify(WaitNotifyData theAwaitingDataP)
189      { ////
190        this.theAwaitingData = theAwaitingDataP;
191      }
192      
193      
194      /**This routine overrides <code>Thread.start()</code>, it's a facade. It calls Thread.start() using 
195       * <pre class=Java>
196        /**@java2c=stackSize(TestThreadLocalData+500). * /
197        super.start();
198       * </pre>
199       * It is a facade, containing the stacksize annotation regarded in Java2C-translation.
200       * The produced C-Code is:
201       * <pre clas=CCode>
202        start_ThreadJc(ythis, sizeof(TestWaitNotify_Test__TestThreadLocalData_s)+500, _thCxt);
203       * <pre>
204       * @see {@link java.lang.Thread#start()}
205       */
206      @Override public void start()
207      {
208        /**@java2c=stackSize(TestThreadLocalData+500). */
209        super.start();
210      }
211      
212      
213      
214      /**This is the thread main-routine complying the Java rules. The routine is started 
215       * if the ,,start(),,-method of this instance is called. 
216       * <br><br>
217       * This routine creates an instances {@link TestThreadLocalData}, which are accessed by this thread only.
218       * In Java the instances are referenced, but the reference is only known in stack context,
219       * provided to called routines via parameter. In C the instances are allocated in the stack
220       * because a <code>@ java2c=stackInstance.</code> is written thereby. Large-size instances need
221       * an adequate stack size. The Java-code for this code-snippet is:
222       * <pre class="Java">
223         ...* @java2c=stackInstance. * /
224        TestThreadLocalData threadLocalData = new TestThreadLocalData();
225       * </pre>
226       * The generated C-code is:
227       * <pre class="CCode">
228        TestThread_Test__TestThreadLocalData_s threadLocalData;  
229        ...
230        init_ObjectJc(&(threadLocalData.base.object), sizeof(threadLocalData), 0); 
231        ctorO_TestThread_Test__TestThreadLocalData(&(threadLocalData.base.object), _thCxt);
232       * </pre>
233       * The thread contains a <code>while</code>-loop with test of {@link #shouldRun} and a sleep in the Java-form:
234       * <pre class="Java">
235        while(shouldRun){
236          threadLocalData.awaitData();
237        }//while
238       * </pre>
239       * In C it is mapped too, but it isn't used yet. 
240       * <br><br>
241       * The C-code of this snippet is:
242       * <pre class="CCode">
243        while(ythis->shouldRun) {
244          awaitData_TestWaitNotify_Test__TestThreadLocalData_F(& (threadLocalData), _thCxt);
245        }
246       * </pre>
247       */
248      public void run(){
249        /**This instance is only visible in the threads context. It is allocated in the stack.
250         * @java2c=stackInstance. */
251        TestThreadLocalData threadLocalData = new TestThreadLocalData(theAwaitingData);
252        while(shouldRun){
253          threadLocalData.awaitData();
254        }//while
255        System.out.println("wait/notify-thread stopped at " + threadLocalData.x);
256        System.out.println("wait/notify-thread: nothingRcv=" + threadLocalData.testCtNothingReceived
257                          + ", successfull=" + threadLocalData.testCtSuccessNotify
258                          + ", missNotify=" + threadLocalData.testCtMissNotify
259                          );
260      }
261    
262    
263      
264    }