Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

threadExample.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 
00057 #include "Aria.h"
00058 
00059 
00060 /* A subclass of ArASyncTask, to contain a method that runs in a new thread */
00061 class ExampleThread : public ArASyncTask
00062 {
00063   ArCondition myCondition;
00064   ArMutex myMutex;
00065   int myCounter;
00066 public:
00067 
00068   /* Construtor. Initialize counter. */
00069   ExampleThread() : myCounter(0)
00070   {
00071   }
00072 
00073 
00074   /* This method is called in the new thread when launched. The void* parameter
00075    * and return value are platform implementation-specific an can be ignored.
00076    * This method will run in a loop, incrementing the counter each second, but 
00077    * locking the mutex to prevent conflicting access by other threads. 
00078    * If it reaches a value divisible by ten, signal our condition variable. If
00079    * it is set to -1, exit the thread.
00080    */
00081   void* runThread(void*) 
00082   {
00083     // Run until the thread is requested to end by another thread.
00084     while(this->getRunningWithLock())
00085     {
00086       myMutex.lock();
00087 
00088       // Increment the counter. 
00089       myCounter++;
00090       ArLog::log(ArLog::Normal, "Example thread: incremented counter to %d.", myCounter);
00091 
00092       // If it's now divisible by 10, signal the condition variable.
00093       if(myCounter % 10 == 0)
00094       {
00095         ArLog::log(ArLog::Normal, "Example thread: Signalling condition.");
00096         myCondition.signal();
00097       }
00098 
00099       // Unlock, then sleep.  We unlock before the sleep, so that while
00100       // we are sleeping, other threads that try to lock the mutex won't
00101       // be blocked until this thread is done sleeping.
00102       myMutex.unlock();
00103       ArUtil::sleep(1000);
00104     }
00105 
00106     ArLog::log(ArLog::Normal, "Example thread: requested stop running, ending thread.");
00107     return NULL;
00108   }
00109 
00110   /* Other threads can call this to wait for a condition eventually
00111    * signalled by this thread.
00112    */
00113   void waitOnCondition()
00114   {
00115     myCondition.wait();
00116   }
00117 
00118   /* Get the counter. Not threadsafe, you must lock the mutex during access. */
00119   int getCounter() { return myCounter; }
00120 
00121   /* Set the countner. Not threadsafe, you must lock the mutex during access. */
00122   void setCounter(int ctr) { myCounter = ctr; }
00123 
00124   /* Lock the mutex object.  */
00125   void lockMutex() { myMutex.lock(); }
00126 
00127   /* Unlock the mutex object. */
00128   void unlockMutex() { myMutex.unlock(); }
00129 
00130 };
00131 
00132 int main()
00133 {
00134   Aria::init();
00135 
00136   ExampleThread exampleThread;
00137 
00138   /* Launch the new thread in the background. This thread (of main()) continues
00139    * immediately. */
00140   ArLog::log(ArLog::Normal, "Main thread: Running new example thread ...");
00141   exampleThread.runAsync();
00142 
00143   /* Loop, reading the value contained in the ExampleThread object.
00144    * We will also use ArUtil::sleep() to make this thread sleep each iteration,
00145    * instead of running as fast as possible and potentially preventing other
00146    * threads from access to the mutex and the shared counter.
00147    * When the counter reaches 10, break out of the loop and then wait on the
00148    * condition variable.
00149    */
00150   while(true)
00151   {
00152     exampleThread.lockMutex();
00153     int c = exampleThread.getCounter();
00154     exampleThread.unlockMutex(); // we can unlock the mutex now, since we made a copy of the counter.
00155 
00156     printf("Main thread: Counter=%d.\n", c);
00157 
00158     if(c >= 10)
00159       break;
00160 
00161     ArUtil::sleep(600);
00162   }
00163 
00164 
00165   /* This shows how to block on an ArCondition object. 
00166    * wait() will *only* return when the condition object is 
00167    * signaled by the other thread.
00168    */
00169   ArLog::log(ArLog::Normal, "Main thread: Waiting on condition object...");
00170   exampleThread.waitOnCondition();
00171 
00172   ArLog::log(ArLog::Normal, "Main thread: Condition was signaled, and execution continued. Telling the other thread to stop running.");
00173   exampleThread.stopRunning();
00174   
00175   ArLog::log(ArLog::Normal, "Main thread: Waiting for the other thread to exit, then exiting the program.");
00176   do {
00177     ArUtil::sleep(250);
00178   } while(exampleThread.getRunningWithLock());
00179 
00180   ArLog::log(ArLog::Normal, "Main thread: Exiting program.");
00181   return 0;
00182 }

Generated on Tue Feb 20 10:51:42 2007 for Aria by  doxygen 1.4.0