![]() |
last update 20 Sep 2009 |
![]() |
00001 /* 00002 * Copyright (C) 1998-2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * Instituto Tecnológico de Costa Rica, Costa Rica 00005 * 00006 * 00007 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00008 * 00009 * The CVR-Lib is free software; you can redistribute it and/or 00010 * modify it under the terms of the BSD License. 00011 * 00012 * All rights reserved. 00013 * 00014 * Redistribution and use in source and binary forms, with or without 00015 * modification, are permitted provided that the following conditions are met: 00016 * 00017 * 1. Redistributions of source code must retain the above copyright notice, 00018 * this list of conditions and the following disclaimer. 00019 * 00020 * 2. Redistributions in binary form must reproduce the above copyright notice, 00021 * this list of conditions and the following disclaimer in the documentation 00022 * and/or other materials provided with the distribution. 00023 * 00024 * 3. Neither the name of the authors nor the names of its contributors may be 00025 * used to endorse or promote products derived from this software without 00026 * specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00029 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00030 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00031 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00032 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00033 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00034 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00035 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00036 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00037 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 */ 00040 00041 00042 /** 00043 * \file cvrGuiServer.h 00044 * Contains the class cvr::guiServer, which manages a singleton that 00045 * controls the thread running the main loop of the used GUI Toolkit 00046 * (like QT, GTK+, GTKMM, WxWidgets, etc.) 00047 * \author Pablo Alvarado 00048 * \date 3.1.2005 00049 * 00050 * revisions ..: $Id: cvrGuiServer.h,v 1.2 2007/10/13 00:18:55 alvarado Exp $ 00051 */ 00052 00053 #ifndef _CVR_GUI_SERVER_H_ 00054 #define _CVR_GUI_SERVER_H_ 00055 00056 #include "cvrConfig.h" 00057 00058 #undef _CVR_HAVE_GUI 00059 00060 // the following code is only interesting if there is a GUI Toolkit available 00061 // At this time only GTK+-2.0 is supported, but this may change in the 00062 // future. 00063 #if defined(HAVE_GTK) || defined(HAVE_QT) || defined(HAVE_WXWIDGETS) 00064 #define _CVR_HAVE_GUI 1 00065 #endif 00066 00067 #ifdef _CVR_HAVE_GUI 00068 00069 #include "cvrMutex.h" 00070 #include "cvrThread.h" 00071 #include "cvrSemaphore.h" 00072 #include "cvrObject.h" 00073 #include "cvrException.h" 00074 00075 namespace cvr { 00076 00077 /** 00078 * Class guiServer. 00079 * 00080 * The guiServer holds the one an only thread which executes the 00081 * main loop of the used GUI Toolkit, like GTK+, GTKMM, WxWidgets, 00082 * QT or MFC. If you are just using the viewers and other GUI 00083 * related classes, this server should never come in your way. 00084 * 00085 * No one can create an instance of the guiServer, which is a 00086 * monostate object. Some public static functions are provided to 00087 * check and alter the state of the main loop: 00088 * - NotStarted 00089 * - Running 00090 * - Stopped 00091 * 00092 * The server can be started only once in the whole program, and 00093 * this will occur automatically when you use any viewer or GUI 00094 * element in the library. If you are writting a new GUI element, 00095 * then you have to ensure that the server is running just before 00096 * you have to interact with any interface related event. It is a 00097 * bad idea to start the server too early, since it will waste some 00098 * time. 00099 * 00100 * The stop() method is provided for completeness and debugging 00101 * purposes only. This method should never ever be called, as the 00102 * main loop cannot be started again, due to limitation of some toolkits. 00103 * 00104 * The general implementation of the current classes is divided in 00105 * the files cvrGuiServer.cpp and lti???Server.cpp, where the latter 00106 * provides the toolkit specific issues (the methods toolkitInit(), 00107 * toolkitMainLoop() and toolkitStop()). 00108 * 00109 * @ingroup gVisualization 00110 */ 00111 class guiServer { 00112 public: 00113 /** 00114 * GUI Server State 00115 */ 00116 enum eServerState { 00117 NotStarted, /**< The server has not been started yet. */ 00118 Running, /**< The server is already running and attending 00119 * GUI requests 00120 */ 00121 Stopped /**< The server has been stopped. */ 00122 }; 00123 00124 /** 00125 * Start the server. 00126 * 00127 * This method returns until the server is running and ready to attend 00128 * requests. 00129 * 00130 * @return true if successful, false otherwise (e.g. the server 00131 * was manually stopped or is already running.) 00132 */ 00133 static bool start(); 00134 00135 /** 00136 * Check for the server state. 00137 */ 00138 static eServerState state(); 00139 00140 /** 00141 * Stop the server. 00142 * 00143 * If the server has not been started at all, this method does nothing, 00144 * but to return false, as it cannot be stopped! 00145 * 00146 * \warning If you stop the server, you cannot re-start it within your 00147 * application. 00148 * This method is public for debuggin purposes and for 00149 * completenes, but you should never call it, unless you really 00150 * know what you are doing. 00151 * 00152 * @return true if the thread could be stopped or false if it was already 00153 * stopped or if the server wasn't started at all. 00154 */ 00155 static bool stop(); 00156 00157 /** 00158 * Returns true if called within the thread attending the main loop 00159 */ 00160 static bool representsGuiThread(); 00161 00162 private: 00163 /** 00164 * Default constructor disabled 00165 */ 00166 guiServer(); 00167 00168 /** 00169 * Disable copy constructor 00170 */ 00171 guiServer(const guiServer& other); 00172 00173 /** 00174 * Disable assignment operator 00175 */ 00176 guiServer& operator=(const guiServer& other); 00177 00178 /** 00179 * Disable destructor 00180 */ 00181 virtual ~guiServer(); 00182 00183 /** 00184 * A unique instance of this class will run the event main loop of 00185 * the GUI toolkit. 00186 * 00187 * @see guiServer 00188 */ 00189 class guiThread : public thread { 00190 public: 00191 /** 00192 * Default constructor 00193 */ 00194 guiThread(); 00195 00196 /** 00197 * Destructor 00198 */ 00199 virtual ~guiThread(); 00200 00201 /** 00202 * Wait until the initialization of the GUI toolkit is ready 00203 */ 00204 void start(); 00205 00206 /** 00207 * Stop the gui-Thread. 00208 */ 00209 virtual void stop(); 00210 00211 /** 00212 * This method is the "slot" to be called when the GUI toolkit reaches 00213 * the normal main-loop, in order to signalize the current thread that 00214 * everything is ok. 00215 */ 00216 void signalizeInitializationReady(); 00217 00218 protected: 00219 /** 00220 * The job to be independently executed in a new thread. This 00221 * function has as task to call the toolkit initialization 00222 * routines (toolkitInit()) and the toolkit main-loop (toolkitMainLoop()) 00223 */ 00224 virtual void run(); 00225 00226 /** 00227 * Clean up the run() method 00228 */ 00229 virtual void cleanUp(); 00230 00231 /** 00232 * Initializes GUI toolkit. 00233 * 00234 * This function is called within the server-thread. 00235 */ 00236 void toolkitInit(); 00237 00238 /** 00239 * Enters event handling routine of the toolkit 00240 * 00241 * This function is called within the server-thread. 00242 */ 00243 void toolkitMainLoop(); 00244 00245 /** 00246 * Tell the main-loop to stop. 00247 * 00248 * This function is called outside the server-thread and blocks 00249 * until the toolkit is really stopped. 00250 */ 00251 void toolkitStop(); 00252 00253 /** 00254 * Semaphore used to indicate if initialization is ready. 00255 * 00256 * The counter of the semaphore is initialized with zero, which 00257 * means that any call to initReady_.wait() will block. As soon as 00258 * the toolkit has been initialized, by some means this semaphore 00259 * has to be unlocked (initReady_.post()). 00260 */ 00261 semaphore initReady_; 00262 00263 /** 00264 * Semaphore used to indicate if finalization is ready. 00265 */ 00266 semaphore finishReady_; 00267 00268 private: 00269 /** 00270 * Disable copy constructor 00271 */ 00272 guiThread(const guiThread& other); 00273 00274 /** 00275 * Disable copy operator 00276 */ 00277 guiThread& operator=(const guiThread& other); 00278 }; 00279 00280 /** 00281 * Pointer to the one and only thread object 00282 */ 00283 static guiThread* thread_; 00284 00285 /** 00286 * Protect access to member from public methods. 00287 */ 00288 static mutex lock_; 00289 00290 /** 00291 * State of the server 00292 */ 00293 static eServerState serverState_; 00294 00295 // the guiThread will want to change the state of this holder. 00296 friend class guiThread; 00297 00298 /** 00299 * Each specific toolkit will need some private access. 00300 * 00301 * This enclosed class is private and knows about its sister class 00302 * guiThread, to which it may require some access. 00303 * 00304 * Since it is still undefined, it is quite flexible to define its 00305 * interface depending on each toolkit. 00306 */ 00307 class server; 00308 00309 /** 00310 * Mark the thread as started 00311 */ 00312 static void markStarted(); 00313 00314 /** 00315 * Mark the thread as stopped in case of normal thread termination 00316 */ 00317 static void markStopped(); 00318 00319 /** 00320 * atexit ensures that this function is called as soon as the main 00321 * program leaves its execution 00322 */ 00323 static void stopForAtExit(); 00324 }; 00325 } 00326 00327 #endif 00328 #endif