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

Aria.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "Aria.h"
00029 #include "ArSocket.h"
00030 #include "ArSignalHandler.h"
00031 #include "ArModuleLoader.h"
00032 #include "ArKeyHandler.h"
00033 #include "ArJoyHandler.h"
00034 #include "ArRobotJoyHandler.h"
00035 
00036 ArGlobalFunctor1<int> Aria::ourSignalHandlerCB(&Aria::signalHandlerCB);
00037 std::list<ArRobot*> Aria::ourRobots;
00038 ArMutex Aria::ourShuttingDownMutex;
00039 bool Aria::ourShuttingDown=false;
00040 std::string Aria::ourDirectory="";
00041 std::list<ArFunctor*> Aria::ourInitCBs;
00042 std::list<ArFunctor*> Aria::ourUninitCBs;
00043 ArKeyHandler *Aria::ourKeyHandler = NULL;
00044 ArJoyHandler *Aria::ourJoyHandler = NULL;
00045 ArRobotJoyHandler *Aria::ourRobotJoyHandler = NULL;
00046 bool Aria::ourInited = false;
00047 bool Aria::ourRunning = false;
00048 ArConfig Aria::ourConfig;
00049 ArMutex Aria::ourExitCallbacksMutex;
00050 std::multimap<int, ArFunctor *> Aria::ourExitCallbacks;
00051 bool Aria::ourSigHandleExitNotShutdown = true;
00052 
00083 void Aria::init(SigHandleMethod method, bool initSockets, 
00084                          bool sigHandleExitNotShutdown)
00085 {
00086   std::list<ArFunctor*>::iterator iter;
00087   std::string str;
00088   char buf[1024];
00089 
00090   if (ourInited == true)
00091     return;
00092 
00093   ourRunning = true;
00094 #ifndef WIN32
00095   srand48(time(NULL));
00096 #endif
00097 
00098   ArThread::init();
00099 
00100   char* overrideSigMethod = getenv("ARIA_SIGHANDLE_METHOD");
00101   if(overrideSigMethod)
00102   {
00103     ArLog::log(ArLog::Terse, "Overriding signal handler method with %s from ARIA_SIGHANDLE_METHOD environment variable.", overrideSigMethod);
00104     if(!strcmp(overrideSigMethod, "NONE"))
00105       method = SIGHANDLE_NONE;
00106     else if(!strcmp(overrideSigMethod, "SINGLE"))
00107       method = SIGHANDLE_SINGLE;
00108     else if(!strcmp(overrideSigMethod, "THREAD"))
00109       method = SIGHANDLE_THREAD;
00110   }
00111 
00112   if (method != SIGHANDLE_NONE)
00113   {
00114     ArSignalHandler::addHandlerCB(&ourSignalHandlerCB, ArListPos::LAST);
00115     ArSignalHandler::blockCommon();
00116     ArSignalHandler::handle(ArSignalHandler::SigHUP);
00117     ArSignalHandler::handle(ArSignalHandler::SigINT);
00118     ArSignalHandler::handle(ArSignalHandler::SigQUIT);
00119     ArSignalHandler::handle(ArSignalHandler::SigTERM);
00120     ArSignalHandler::handle(ArSignalHandler::SigPIPE);
00121     if (method == SIGHANDLE_SINGLE)
00122         ArSignalHandler::createHandlerNonThreaded();
00123     else if (method == SIGHANDLE_THREAD)
00124     {
00125       ArSignalHandler::blockCommonThisThread();
00126       ArSignalHandler::createHandlerThreaded();
00127     }
00128   }
00129 
00130   if (initSockets)
00131     ArSocket::init();
00132 
00133   if (ourDirectory.length() == 0)
00134   {
00135     if (getenv("ARIA") != NULL)
00136     {
00137       setDirectory(getenv("ARIA"));
00138     }
00139     else
00140     {
00141 #ifndef WIN32
00142       ArUtil::getStringFromFile("/etc/Aria", buf, sizeof(buf));
00143       str = buf;
00144 #else // WIN32
00145       if (ArUtil::findFirstStringInRegistry(
00146                                         "SOFTWARE\\ActivMedia Robotics\\Aria",
00147                                         "Install Directory", buf, 1024))
00148         str = buf;
00149       else
00150         str = "";
00151       
00152 #endif // WIN32
00153       if (str.length() > 0)
00154       {
00155         setDirectory(str.c_str());
00156       }
00157       else
00158       {
00159         ArLog::log(ArLog::Terse, "NonCritical Error: ARIA could not find where it is located.");
00160       }
00161     }
00162   }
00163   ourSigHandleExitNotShutdown = sigHandleExitNotShutdown;
00164 
00165   ourInited = true;
00166   for (iter=ourInitCBs.begin(); iter !=  ourInitCBs.end(); ++iter)
00167     (*iter)->invoke();
00168   ArArgumentParser::addDefaultArgumentFile("/etc/Aria.args");
00169   ArArgumentParser::addDefaultArgumentEnv("ARIAARGS");
00170   
00171 }
00172 
00178 void Aria::uninit()
00179 {
00180   std::list<ArFunctor*>::iterator iter;
00181 
00182   for (iter=ourUninitCBs.begin(); iter != ourUninitCBs.end(); ++iter)
00183     (*iter)->invoke();
00184 
00185   ArModuleLoader::closeAll();
00186   ArSocket::shutdown();
00187 }
00188 
00193 void Aria::addInitCallBack(ArFunctor *cb, ArListPos::Pos position)
00194 {
00195   if (position == ArListPos::FIRST)
00196     ourInitCBs.push_front(cb);
00197   else
00198     ourInitCBs.push_back(cb);
00199 }
00200 
00208 void Aria::addUninitCallBack(ArFunctor *cb, ArListPos::Pos position)
00209 {
00210   if (position == ArListPos::FIRST)
00211     ourUninitCBs.push_front(cb);
00212   else
00213     ourUninitCBs.push_back(cb);
00214 }
00215 
00222 void Aria::shutdown()
00223 {
00224   bool doExit=false;
00225 
00226   ourShuttingDownMutex.lock();
00227   ourRunning = false;
00228   if (ourShuttingDown)
00229     doExit=true;
00230   else
00231     ourShuttingDown=true;
00232   ourShuttingDownMutex.unlock();
00233 
00234   if (doExit)
00235     return;
00236 
00237   ArThread::stopAll();
00238   ArThread::joinAll();
00239   uninit();
00240 }
00241 
00248 void Aria::exit(int exitCode)
00249 {
00250   bool doReturn = false;
00251   ourShuttingDownMutex.lock();
00252   ourRunning = false;
00253   if (ourShuttingDown)
00254     doReturn=true;
00255   else
00256     ourShuttingDown=true;
00257   ourShuttingDownMutex.unlock();
00258 
00259   if (doReturn)
00260     return;
00261 
00262   callExitCallbacks();
00263   ::exit(exitCode);
00264 }
00265 
00266 void Aria::callExitCallbacks(void)
00267 {
00268   ourRunning = false;
00269   std::multimap<int, ArFunctor *>::reverse_iterator it;
00270  
00271   ourExitCallbacksMutex.lock();
00272   ArLog::log(ArLog::Verbose, "Aria::exit: Starting exit callbacks");
00273   for (it = ourExitCallbacks.rbegin(); it != ourExitCallbacks.rend(); it++)
00274   {
00275     ArLog::log(ArLog::Verbose, 
00276                "Aria::exit: Calling callback at position %d with name '%s'",
00277                (*it).first, (*it).second->getName());
00278     (*it).second->invoke();
00279   }
00280   ArLog::log(ArLog::Verbose, "Aria::exit: Finished exit callbacks");
00281   ourExitCallbacksMutex.unlock();
00282 } 
00283  
00284 void Aria::addExitCallback(ArFunctor *functor, int position)
00285 {
00286   ourExitCallbacksMutex.lock();
00287   ArLog::log(ArLog::Verbose, 
00288         "Aria::addExitCallback: Adding callback at position %d with name '%s'",
00289              position, functor->getName());
00290   ourExitCallbacks.insert(std::pair<int, ArFunctor *>(position, functor));
00291   ourExitCallbacksMutex.unlock();
00292 }
00293 
00294 /*
00295 void Aria::remExitCallback(ArFunctor *functor)
00296 {
00297   std::multimap<int, ArFunctor *>::iterator it;
00298   
00299   ourExitCallbacksMutex.lock();
00300   for (it = ourExitCallbacks.begin(); it != ourExitCallbacks.end(); it++)
00301   {
00302     if ((*it).second == functor)
00303     {
00304       ourExitCallbacks.erase(it);
00305       ourExitCallbacksMutex.unlock();
00306       return remExitCallback(functor);
00307     }
00308   }
00309   ourExitCallbacksMutex.unlock();
00310 }
00311 */
00312 
00326 void Aria::exitOld(int exitCode)
00327 {
00328   ourRunning = false;
00329   ArThread::cancelAll();
00330   uninit();
00331   ::exit(exitCode);
00332 }
00333 
00334 void Aria::addRobot(ArRobot *robot)
00335 {
00336   ourRobots.push_back(robot);
00337 }
00338 
00339 void Aria::delRobot(ArRobot *robot)
00340 {
00341   ourRobots.remove(robot);
00342 }
00343 
00349 ArRobot *Aria::findRobot(char *name)
00350 {
00351   std::string rname;
00352   std::list<ArRobot *>::iterator it;
00353   if (name == NULL)
00354     return NULL;
00355 
00356   rname = name;
00357   for (it = ourRobots.begin(); it != ourRobots.end(); it++)
00358   {
00359     if ((*it)->getName() == rname)
00360       return (*it);
00361   }
00362   return NULL;
00363 
00364 }
00365 
00366 std::list<ArRobot*> * Aria::getRobotList()
00367 {
00368   return(&ourRobots);
00369 }
00370 
00371 void Aria::signalHandlerCB(int sig)
00372 {
00373   std::list<ArRobot*>::iterator iter;
00374 
00375   // if we want to exit instead of shutdown then do that ( call never returns)
00376   if (ourSigHandleExitNotShutdown)
00377   {
00378     ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Exiting.",
00379                ArSignalHandler::nameSignal(sig));
00380     Aria::exit(0);
00381   }
00382 
00383 
00384   ourShuttingDownMutex.lock();
00385   if (!ourRunning)
00386   {
00387     ourShuttingDownMutex.unlock();
00388     return;
00389   }
00390   ourShuttingDownMutex.unlock();
00391 
00392 
00393   ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Shutting down.",
00394              ArSignalHandler::nameSignal(sig));
00395   if ((sig == ArSignalHandler::SigINT) || (sig == ArSignalHandler::SigHUP) ||
00396       (sig == ArSignalHandler::SigTERM))
00397   {
00398     for (iter=ourRobots.begin(); iter != ourRobots.end(); ++iter)
00399       (*iter)->stopRunning();
00400   }
00401 
00402   // I'm disregarding this advice below since I can't seem to get
00403   // anything else to work well and haven't seen problems from it
00404 
00405   // dont do an Aria::shutdown() here because we want the main()
00406   // function to do the ArThread::joinAll(). Otherwise variables on
00407   // the stack frame of main() may get destructed if main() happens to
00408   // exit before other threads.  And some of those variables may be
00409   // used by those threads.
00410   shutdown();
00411 }
00412 
00421 void Aria::setDirectory(const char *directory)
00422 {
00423   int ind;
00424   if (directory != NULL)
00425   {
00426     ourDirectory = directory;
00427     ind = strlen(directory) - 1;
00428     if (ind < 0)
00429       ind = 0;
00430     if (directory[ind] != '/' && directory[ind] != '\\')
00431     {
00432 #ifdef WIN32
00433       ourDirectory += "\\";
00434 #else // win32
00435       ourDirectory += "/";
00436 #endif // win32
00437     }
00438     ourConfig.setBaseDirectory(ourDirectory.c_str());
00439   }
00440 }
00441 
00448 const char *Aria::getDirectory(void)
00449 {
00450   return ourDirectory.c_str();
00451 }
00452 
00454 void Aria::setKeyHandler(ArKeyHandler *keyHandler)
00455 {
00456   ourKeyHandler = keyHandler;
00457 }
00458 
00460 ArKeyHandler *Aria::getKeyHandler(void)
00461 {
00462   return ourKeyHandler;
00463 }
00464 
00466 void Aria::setJoyHandler(ArJoyHandler *joyHandler)
00467 {
00468   ourJoyHandler = joyHandler;
00469 }
00470 
00472 ArJoyHandler *Aria::getJoyHandler(void)
00473 {
00474   return ourJoyHandler;
00475 }
00476 
00477 
00479 void Aria::setRobotJoyHandler(ArRobotJoyHandler *robotJoyHandler)
00480 {
00481   ourRobotJoyHandler = robotJoyHandler;
00482 }
00483 
00485 ArRobotJoyHandler *Aria::getRobotJoyHandler(void)
00486 {
00487   return ourRobotJoyHandler;
00488 }
00489 
00495 bool Aria::getRunning(void)
00496 {
00497   return ourRunning;
00498 }
00499 
00503 ArConfig *Aria::getConfig(void)
00504 {
00505   return &ourConfig;
00506 }
00507 
00508 

Generated on Wed Oct 19 12:56:35 2005 for Aria by  doxygen 1.4.0