sdl_keeper.cpp

00001
00002 /***************************************************************************
00003  *  sdl_keeper.cpp - utility to keep track of SDL initialization state
00004  *
00005  *  Created: Mon Nov 05 14:34:36 2007
00006  *  Copyright  2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include <fvwidgets/sdl_keeper.h>
00025
00026 #include <core/threading/mutex.h>
00027 #include <core/threading/mutex_locker.h>
00028 #include <core/exception.h>
00029
00030 #include <SDL.h>
00031
00032 using namespace fawkes;
00033
00034 unsigned int SDLKeeper::_refcount = 0;
00035 Mutex        SDLKeeper::_mutex;
00036
00037 
00038 /** @class SDLKeeper <fvwidgets/sdl_keeper.h>
00039  * SDL Reference keeper.
00040  *
00041  * Use this keeper to initialize and quit the SDL library. As there may be many
00042  * modules using the SDL a central place for reference counting is needed.
00043  *
00044  * @author Tim Niemueller
00045  */
00046 
00047 /** Private inaccessible constructor. */
00048 SDLKeeper::SDLKeeper()
00049 {
00050 }
00051
00052 
00053 /** Init SDL.
00054  * Keeps track of SDL_Init calls and only calls SDL_InitSubSystem on consecutive
00055  * calls.
00056  * @param flags Same flags as for SDL_Init
00057  */
00058 void
00059 SDLKeeper::init(unsigned int flags)
00060 {
00061   MutexLocker lock(&_mutex);
00062
00063   unsigned int alive_subsys = SDL_WasInit(SDL_INIT_EVERYTHING);
00064   if ( (alive_subsys & flags) != flags ) {
00065     // Subsystem has not been initialized, yet
00066     if ( _refcount == 0 ) {
00067       if ( SDL_Init(flags) != 0 ) {
00068         throw Exception("SDL: initialization failed");
00069       }
00070     } else {
00071       unsigned int still_to_init = ~alive_subsys & flags;
00072       if ( SDL_Init(still_to_init) != 0 ) {
00073         throw Exception("SDL: initialization failed");
00074       }
00075     }
00076   }
00077
00078   ++_refcount;
00079 }
00080
00081 
00082 /** Conditionally quit SDL.
00083  * Use this after you are done with the SDL. No subsystem will be closed after all
00084  * users of SDL quit the usage. Then the whole SDL will be released at once.
00085  */
00086 void
00087 SDLKeeper::quit() throw()
00088 {
00089   MutexLocker lock(&_mutex);
00090
00091   if ( (_refcount > 0) && (--_refcount == 0) ) {
00092     SDL_Quit();
00093   }
00094 }
00095
00096 
00097 /** Force quit of SDL.
00098  * This will quit the SDL no matter of the reference count. Use with extreme care.
00099  */
00100 void
00101 SDLKeeper::force_quit()
00102 {
00103   MutexLocker lock(&_mutex);
00104
00105   SDL_Quit();
00106   _refcount = 0;
00107 }