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