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 }