Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Jul 29, 2009, 5:24:39 PM (15 years ago)
Author:
rgrieder
Message:

Exception-safety for the Game and Core c'tors as well as load/unload-Graphics.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/resource/src/core/Game.cc

    r3359 r3363  
    4040#include "util/Debug.h"
    4141#include "util/Exception.h"
     42#include "util/ScopeGuard.h"
    4243#include "util/Sleep.h"
    4344#include "util/SubString.h"
     
    133134
    134135        // Set up a basic clock to keep time
    135         this->gameClock_ = new Clock();
     136        this->gameClock_.reset(new Clock());
    136137
    137138        // Create the Core
    138         this->core_ = new Core(cmdLine);
     139        this->core_.reset(new Core(cmdLine));
    139140
    140141        // After the core has been created, we can safely instantiate the GameStates that don't require graphics
     
    153154
    154155        // Do this after the Core creation!
    155         this->configuration_ = new GameConfiguration();
     156        this->configuration_.reset(new GameConfiguration());
    156157    }
    157158
    158159    /**
    159160    @brief
     161        All destruction code is handled by scoped_ptrs and SimpleScopeGuards.
    160162    */
    161163    Game::~Game()
    162164    {
    163         // Destroy the configuration helper class instance
    164         delete this->configuration_;
    165 
    166         // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
    167         for (std::map<std::string, GameState*>::const_iterator it = constructedStates_.begin();
    168             it != constructedStates_.end(); ++it)
    169             delete it->second;
    170 
    171         // Destroy the Core and with it almost everything
    172         delete this->core_;
    173         delete this->gameClock_;
    174 
    175         // Take care of the GameStateFactories
    176         GameStateFactory::destroyFactories();
    177 
    178165        // Don't assign singletonRef_s with NULL! Recreation is not supported
    179166    }
     
    283270    {
    284271        // Note: The first element is the empty root state, which doesn't need ticking
    285         for (std::vector<GameState*>::const_iterator it = this->loadedStates_.begin() + 1;
     272        for (GameStateVector::const_iterator it = this->loadedStates_.begin() + 1;
    286273            it != this->loadedStates_.end(); ++it)
    287274        {
     
    457444    }
    458445
    459     GameState* Game::getState(const std::string& name)
    460     {
    461         std::map<std::string, GameState*>::const_iterator it = constructedStates_.find(name);
     446    shared_ptr<GameState> Game::getState(const std::string& name)
     447    {
     448        GameStateMap::const_iterator it = constructedStates_.find(name);
    462449        if (it != constructedStates_.end())
    463450            return it->second;
     
    469456            else
    470457                COUT(1) << "Error: Could not find GameState '" << name << "'." << std::endl;
    471             return 0;
     458            return shared_ptr<GameState>();
    472459        }
    473460    }
     
    528515        {
    529516            core_->loadGraphics();
     517            Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics);
    530518            GameMode::bShowsGraphics_s = true;
    531519
     
    536524                if (it->second.bGraphicsMode)
    537525                {
     526                    // Game state loading failure is serious --> don't catch
     527                    shared_ptr<GameState> gameState = GameStateFactory::fabricate(it->second);
    538528                    if (!constructedStates_.insert(std::make_pair(
    539                         it->second.stateName, GameStateFactory::fabricate(it->second))).second)
     529                        it->second.stateName, gameState)).second)
    540530                        assert(false); // GameState was already created!
    541531                }
    542532            }
     533            graphicsUnloader.Dismiss();
    543534        }
    544535    }
     
    549540        {
    550541            // Destroy all the GameStates that require graphics
    551             for (std::map<std::string, GameState*>::iterator it = constructedStates_.begin(); it != constructedStates_.end();)
     542            for (GameStateMap::iterator it = constructedStates_.begin(); it != constructedStates_.end();)
    552543            {
    553544                if (it->second->getInfo().bGraphicsMode)
    554                 {
    555                     delete it->second;
    556545                    constructedStates_.erase(it++);
    557                 }
    558546                else
    559547                    ++it;
     
    577565    {
    578566        this->bChangingState_ = true;
     567        LOKI_ON_BLOCK_EXIT_OBJ(*this, &Game::resetChangingState);
     568
    579569        // If state requires graphics, load it
    580         if (gameStateDeclarations_s[name].bGraphicsMode)
     570        Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics);
     571        if (gameStateDeclarations_s[name].bGraphicsMode && !GameMode::showsGraphics())
    581572            this->loadGraphics();
    582         GameState* state = this->getState(name);
     573        else
     574            graphicsUnloader.Dismiss();
     575
     576        shared_ptr<GameState> state = this->getState(name);
    583577        state->activate();
    584578        if (!this->loadedStates_.empty())
     
    586580        this->loadedStates_.push_back(state);
    587581        state->activity_.topState = true;
    588         this->bChangingState_ = false;
     582
     583        graphicsUnloader.Dismiss();
    589584    }
    590585
    591586    void Game::unloadState(const std::string& name)
    592587    {
    593         GameState* state = this->getState(name);
    594588        this->bChangingState_ = true;
    595         state->activity_.topState = false;
    596         this->loadedStates_.pop_back();
    597         if (!this->loadedStates_.empty())
    598             this->loadedStates_.back()->activity_.topState = true;
    599589        try
    600590        {
     591            shared_ptr<GameState> state = this->getState(name);
     592            state->activity_.topState = false;
     593            this->loadedStates_.pop_back();
     594            if (!this->loadedStates_.empty())
     595                this->loadedStates_.back()->activity_.topState = true;
    601596            state->deactivate();
    602             // Check if graphis is still required
    603             bool graphicsRequired = false;
    604             for (unsigned i = 0; i < loadedStates_.size(); ++i)
    605                 graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
    606             if (!graphicsRequired)
    607                 this->unloadGraphics();
    608597        }
    609598        catch (const std::exception& ex)
     
    612601            COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
    613602        }
     603        // Check if graphics is still required
     604        bool graphicsRequired = false;
     605        for (unsigned i = 0; i < loadedStates_.size(); ++i)
     606            graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
     607        if (!graphicsRequired)
     608            this->unloadGraphics();
    614609        this->bChangingState_ = false;
    615610    }
    616611
    617     std::map<std::string, Game::GameStateFactory*> Game::GameStateFactory::factories_s;
    618 
    619     /*static*/ GameState* Game::GameStateFactory::fabricate(const GameStateInfo& info)
    620     {
    621         std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.find(info.className);
     612    std::map<std::string, shared_ptr<Game::GameStateFactory> > Game::GameStateFactory::factories_s;
     613
     614    /*static*/ shared_ptr<GameState> Game::GameStateFactory::fabricate(const GameStateInfo& info)
     615    {
     616        std::map<std::string, shared_ptr<Game::GameStateFactory> >::const_iterator it = factories_s.find(info.className);
    622617        assert(it != factories_s.end());
    623618        return it->second->fabricateInternal(info);
    624619    }
    625 
    626     /*static*/ void Game::GameStateFactory::destroyFactories()
    627     {
    628         for (std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.begin(); it != factories_s.end(); ++it)
    629             delete it->second;
    630         factories_s.clear();
    631     }
    632620}
Note: See TracChangeset for help on using the changeset viewer.