This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Ticket #3708: JS_ShutDown_SVN_1.0.diff

File JS_ShutDown_SVN_1.0.diff, 7.6 KB (added by Yves, 8 years ago)

JS_Shutdown patch for SVN with validation and RAII approach

  • source/main.cpp

     
    7373#include "graphics/TextureManager.h"
    7474#include "gui/GUIManager.h"
    7575#include "renderer/Renderer.h"
     76#include "scriptinterface/ScriptEngine.h"
    7677#include "simulation2/Simulation2.h"
    7778
    7879#if OS_UNIX
     
    422423        return;
    423424    }
    424425
    425     // We need to initialise libxml2 in the main thread before
    426     // any thread uses it. So initialise it here before we
    427     // might run Atlas.
     426    // We need to initialize libxml2 and SpiderMonkey in the main thread before
     427    // any thread uses them. So initialize them here before we might run Atlas.
    428428    CXeromyces::Startup();
     429    ScriptEngine scriptEngine;
    429430
    430431    // Atlas handles the whole init/shutdown/etc sequence by itself;
    431432    if (ATLAS_RunIfOnCmdLine(args, false))
  • source/scriptinterface/ScriptEngine.h

     
     1/* Copyright (C) 2016 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_SCRIPTENGINE
     19#define INCLUDED_SCRIPTENGINE
     20
     21#include "ScriptTypes.h"
     22#include "ps/Singleton.h"
     23
     24/**
     25 * A class using the RAII (Resource Acquisition Is Initialization) idiom to manage initialization
     26 * and shutdown of the SpiderMonkey script engine. It also keeps a count of active script runtimes
     27 * in order to validate the following constraints:
     28 *  1. JS_Init must be called before any ScriptRuntimes are initialized
     29 *  2. JS_Shutdown must be called after all ScriptRuntimes have been destroyed
     30 */
     31
     32class ScriptEngine : public Singleton<ScriptEngine>
     33{
     34public:
     35    ScriptEngine()
     36    {
     37        ENSURE(m_Runtimes.size() == 0 && "JS_Init must be called before any runtimes are created!");
     38        JS_Init();
     39    }
     40
     41    ~ScriptEngine()
     42    {
     43        ENSURE(m_Runtimes.size() == 0 && "All runtimes must be destroyed before calling JS_ShutDown!");
     44        JS_ShutDown();
     45    }
     46
     47    void RegisterRuntime(const JSRuntime* rt) { m_Runtimes.push_back(rt); }
     48    void UnRegisterRuntime(const JSRuntime* rt) { m_Runtimes.remove(rt); }
     49
     50private:
     51
     52    std::list<const JSRuntime*> m_Runtimes;
     53};
     54
     55#endif // INCLUDED_SCRIPTENGINE
  • source/scriptinterface/ScriptInterface.cpp

     
    433433    }
    434434}
    435435
    436 void ScriptInterface::ShutDown()
    437 {
    438     JS_ShutDown();
    439 }
    440 
    441436void ScriptInterface::SetCallbackData(void* pCBData)
    442437{
    443438    m_CxPrivate.pCBData = pCBData;
  • source/scriptinterface/ScriptInterface.h

     
    9797
    9898    ~ScriptInterface();
    9999
    100     /**
    101      * Shut down the JS system to clean up memory. Must only be called when there
    102      * are no ScriptInterfaces alive.
    103      */
    104     static void ShutDown();
    105 
    106100    struct CxPrivate
    107101    {
    108102        ScriptInterface* pScriptInterface; // the ScriptInterface object the current context belongs to
  • source/scriptinterface/ScriptRuntime.cpp

     
    2121
    2222#include "ps/GameSetup/Config.h"
    2323#include "ps/Profile.h"
     24#include "scriptinterface/ScriptEngine.h"
    2425
    2526
    2627void GCSliceCallbackHook(JSRuntime* UNUSED(rt), JS::GCProgress progress, const JS::GCDescription& UNUSED(desc))
     
    104105    m_FinalizationListObjectIdCache.push_back(obj);
    105106}
    106107
    107 bool ScriptRuntime::m_Initialized = false;
    108 
    109108ScriptRuntime::ScriptRuntime(shared_ptr<ScriptRuntime> parentRuntime, int runtimeSize, int heapGrowthBytesGCTrigger):
    110109    m_LastGCBytes(0),
    111110    m_LastGCCheck(0.0f),
     
    112111    m_HeapGrowthBytesGCTrigger(heapGrowthBytesGCTrigger),
    113112    m_RuntimeSize(runtimeSize)
    114113{
    115     if (!m_Initialized)
    116     {
    117         ENSURE(JS_Init());
    118         m_Initialized = true;
    119     }
     114    ENSURE(ScriptEngine::IsInitialised() && "The ScriptEngine must be initialized before constructing any ScriptRuntimes!");
    120115
    121116    JSRuntime* parentJSRuntime = parentRuntime ? parentRuntime->m_rt : nullptr;
    122117    m_rt = JS_NewRuntime(runtimeSize, JS_USE_HELPER_THREADS, parentJSRuntime);
     
    135130   
    136131    m_dummyContext = JS_NewContext(m_rt, STACK_CHUNK_SIZE);
    137132    ENSURE(m_dummyContext);
     133
     134    ScriptEngine::GetSingleton().RegisterRuntime(m_rt);
    138135}
    139136
    140137ScriptRuntime::~ScriptRuntime()
     
    143140    JS_SetGCCallback(m_rt, nullptr, nullptr);
    144141    JS_DestroyRuntime(m_rt);
    145142    ENSURE(m_FinalizationListObjectIdCache.empty() && "Leak: Removing callback while some objects still aren't finalized!");
     143
     144    ENSURE(ScriptEngine::IsInitialised() && "The ScriptEngine must be active (initiaized and not yet shut down) when destroying a ScriptRuntime!");
     145    ScriptEngine::GetSingleton().UnRegisterRuntime(m_rt);
    146146}
    147147
    148148void ScriptRuntime::RegisterContext(JSContext* cx)
  • source/scriptinterface/ScriptRuntime.h

     
    7979   
    8080    std::list<JSContext*> m_Contexts;
    8181    std::vector<std::shared_ptr<void> > m_FinalizationListObjectIdCache;
    82     static bool m_Initialized;
    8382
    8483    int m_RuntimeSize;
    8584    int m_HeapGrowthBytesGCTrigger;
  • source/test_setup.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3636#include "lib/timer.h"
    3737#include "lib/sysdep/sysdep.h"
    3838#include "ps/Profiler2.h"
     39#include "scriptinterface/ScriptEngine.h"
    3940#include "scriptinterface/ScriptInterface.h"
    4041
    4142class LeakReporter : public CxxTest::GlobalFixture
     
    4243{
    4344    virtual bool tearDownWorld()
    4445    {
    45         // Shut down JS to prevent leak reports from it
    46         ScriptInterface::ShutDown();
    47 
    4846        // Enable leak reporting on exit.
    4947        // (This is done in tearDownWorld so that it doesn't report 'leaks'
    5048        // if the program is aborted before finishing cleanly.)
     
    8179        ThreadUtil::SetMainThread();
    8280
    8381        g_Profiler2.Initialise();
     82        m_ScriptEngine = new ScriptEngine;
    8483        g_ScriptRuntime = ScriptInterface::CreateRuntime();
    8584
    8685        return true;
     
    8988    virtual bool tearDownWorld()
    9089    {
    9190        g_ScriptRuntime.reset();
     91        delete m_ScriptEngine;
    9292        g_Profiler2.Shutdown();
    9393
    9494        return true;
    9595    }
     96
     97private:
     98
     99    // We're doing the initialization and shutdown of the ScriptEngine explicitly here
     100    // to make sure it's only initialized when setUpWorld is called.
     101    ScriptEngine* m_ScriptEngine;
    96102};
    97103
    98104static LeakReporter leakReporter;