CVR-Lib last update 20 Sep 2009

cvrGuiServer.h

Go to the documentation of this file.
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

Generated on Sun Sep 20 22:07:59 2009 for CVR-Lib by Doxygen 1.5.8