Changeset 25326

Timestamp:
Apr 27, 2021, 9:45:40 AM (3 years ago)
Author:
wraitii
Message:

De-singletonify CConfigDB, make hooks RAII.

CConfigDB is no longer a singleton, and its members are no longer static.
This makes it possible to have several instances of it, useful for testing of if we ever want to have different config profiles.

Also updates hooks to delete themselves on destruction, to fit a more natural RAII pattern. Long-lived objects must take care to destroy hooks before ConfigDB is reset.

Differential Revision: https://code.wildfiregames.com/D3866

Location:
ps/trunk/source
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/source/graphics/ObjectManager.cpp

    r25308 r25326  
    5252    RegisterFileReloadFunc(ReloadChangedFileCB, this);
    5353
    54     m_QualityHook = std::make_unique<CConfigDBHook>(g_ConfigDB.RegisterHookAndCall("max_actor_quality", [this]() { this->ActorQualityChanged(); }));
     54    m_QualityHook = std::make_unique<CConfigDBHook>(g_ConfigDB.RegisterHookAndCall("max_actor_quality", [this]() { ActorQualityChanged(); }));
    5555
    5656    if (!CXeromyces::AddValidator(g_VFS, "actor", "art/actors/actor.rng"))
     
    6161{
    6262    UnloadObjects();
    63 
    64     g_ConfigDB.UnregisterHook(std::move(m_QualityHook));
    6563
    6664    UnregisterFileReloadFunc(ReloadChangedFileCB, this);
  • ps/trunk/source/gui/tests/test_GuiManager.h

    r25169 r25326  
    2727#include "ps/XML/Xeromyces.h"
    2828
     29
     30
    2931class TestGuiManager : public CxxTest::TestSuite
    3032{
    31     CConfigDB* configDB;
     33    configDB;
    3234public:
    3335
     
    3840        TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY));
    3941
    40         configDB = new CConfigDB;
     42        configDB = ;
    4143
    4244        CXeromyces::Startup();
     
    4951        delete g_GUI;
    5052        CXeromyces::Terminate();
    51         delete configDB;
     53        ;
    5254        g_VFS.reset();
    5355        DeleteDirectory(DataDir()/"_testcache");
     
    190192        TS_ASSERT_EQUALS(hotkey_pressed_value, false);
    191193
    192         configDB->RemoveValue(CFG_SYSTEM, test_hotkey_name);
    193194        UnloadHotkeys();
    194195    }
  • ps/trunk/source/ps/ConfigDB.cpp

    r25279 r25326  
    3838}
    3939
    40 std::recursive_mutex g_ConfigDBMutex;
    41 
    4240// These entries will not be printed to logfiles, so that logfiles can be shared without leaking personal or sensitive data
    4341const std::unordered_set<std::string> g_UnloggedEntries = {
     
    9088
    9189typedef std::map<CStr, CConfigValueSet> TConfigMap;
    92 TConfigMap CConfigDB::m_Map[CFG_LAST];
    93 VfsPath CConfigDB::m_ConfigFile[CFG_LAST];
    94 bool CConfigDB::m_HasChanges[CFG_LAST];
    95 
    96 std::multimap<CStr, std::function<void()>> CConfigDB::m_Hooks;
    9790
    9891#define GETVAL(type)\
     
    10093    {\
    10194        CHECK_NS(;);\
    102         std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);\
     95        std::lock_guard<std::recursive_mutex> s(Mutex);\
    10396        TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);\
    10497        if (it != m_Map[CFG_COMMAND].end())\
     
    127120#undef GETVAL
    128121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
     132
     133
     134
     135
     136
     137
     138
     139
     140
     141
     142
     143
     144
     145
     146
     147
     148
     149
     150
     151
    129152bool CConfigDB::HasChanges(EConfigNamespace ns) const
    130153{
    131154    CHECK_NS(false);
    132155
    133     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     156    std::lock_guard<std::recursive_mutex> s(Mutex);
    134157    return m_HasChanges[ns];
    135158}
     
    139162    CHECK_NS(;);
    140163
    141     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     164    std::lock_guard<std::recursive_mutex> s(Mutex);
    142165    m_HasChanges[ns] = value;
    143166}
     
    147170    CHECK_NS(;);
    148171
    149     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
    150     TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);
     172    std::lock_guard<std::recursive_mutex> s(Mutex);
     173    TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);
    151174    if (it != m_Map[CFG_COMMAND].end())
    152175    {
     
    170193    CHECK_NS(CFG_LAST);
    171194
    172     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
    173     TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);
     195    std::lock_guard<std::recursive_mutex> s(Mutex);
     196    TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);
    174197    if (it != m_Map[CFG_COMMAND].end())
    175198        return CFG_COMMAND;
     
    187210std::map<CStr, CConfigValueSet> CConfigDB::GetValuesWithPrefix(EConfigNamespace ns, const CStr& prefix) const
    188211{
    189     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     212    std::lock_guard<std::recursive_mutex> s(Mutex);
    190213    std::map<CStr, CConfigValueSet> ret;
    191214
     
    210233    CHECK_NS(;);
    211234
    212     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     235    std::lock_guard<std::recursive_mutex> s(Mutex);
    213236    TConfigMap::iterator it = m_Map[ns].find(name);
    214237    if (it == m_Map[ns].end())
     
    233256    CHECK_NS(;);
    234257
    235     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     258    std::lock_guard<std::recursive_mutex> s(Mutex);
    236259    TConfigMap::iterator it = m_Map[ns].find(name);
    237260    if (it == m_Map[ns].end())
     
    245268    CHECK_NS(;);
    246269
    247     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     270    std::lock_guard<std::recursive_mutex> s(Mutex);
    248271    TConfigMap::iterator it = m_Map[ns].find(name);
    249272    if (it == m_Map[ns].end())
     
    258281    CHECK_NS(;);
    259282
    260     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     283    std::lock_guard<std::recursive_mutex> s(Mutex);
    261284    m_ConfigFile[ns] = path;
    262285}
     
    266289    CHECK_NS(false);
    267290
    268     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     291    std::lock_guard<std::recursive_mutex> s(Mutex);
    269292
    270293    shared_ptr<u8> buffer;
     
    429452    CHECK_NS(false);
    430453
    431     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     454    std::lock_guard<std::recursive_mutex> s(Mutex);
    432455    return WriteFile(ns, m_ConfigFile[ns]);
    433456}
     
    437460    CHECK_NS(false);
    438461
    439     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     462    std::lock_guard<std::recursive_mutex> s(Mutex);
    440463    shared_ptr<u8> buf;
    441464    AllocateAligned(buf, 1*MiB, maxSectorSize);
     
    469492    CHECK_NS(false);
    470493
    471     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     494    std::lock_guard<std::recursive_mutex> s(Mutex);
    472495    return WriteValueToFile(ns, name, value, m_ConfigFile[ns]);
    473496}
     
    477500    CHECK_NS(false);
    478501
    479     std::lock_guard<std::recursive_mutex> s(g_ConfigDBMutex);
     502    std::lock_guard<std::recursive_mutex> s(Mutex);
    480503
    481504    TConfigMap newMap;
     
    492515{
    493516    hook();
     517
    494518    return CConfigDBHook(*this, m_Hooks.emplace(name, hook));
    495519}
     
    498522{
    499523    if (hook.m_Ptr != m_Hooks.end())
     524
     525
    500526        m_Hooks.erase(hook.m_Ptr);
     527
     528
    501529}
    502530
  • ps/trunk/source/ps/ConfigDB.h

    r25279 r25326  
    3030#include "lib/file/vfs/vfs_path.h"
    3131#include "ps/CStr.h"
    32 #include "ps/Singleton.h"
    33 
     32
     33#include <array>
    3434#include <map>
     35
     36
    3537#include <vector>
    3638
     
    6062class CConfigDBHook;
    6163
    62 #define g_ConfigDB CConfigDB::GetSingleton()
    63 
    64 class CConfigDB : public Singleton<CConfigDB>
     64#define g_ConfigDB )
     65
     66class CConfigDB
    6567{
    6668    friend CConfigDBHook;
    6769public:
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
    6880    /**
    6981     * Attempt to retrieve the value of a config variable with the given name;
     
    179191     * This is simple on purpose, the hook is responsible for checking if it should do something.
    180192     * When RegisterHookAndCall is called, the hook is immediately triggered.
    181      */
    182     CConfigDBHook RegisterHookAndCall(const CStr& name, std::function<void()> hook);
     193     * NB: CConfigDBHook will auto-unregister the hook when destroyed,
     194     * so you can use it to tie the lifetime of the hook to your object.
     195     * The hook will be deleted alongside ConfigDB anyways.
     196     */
     197    [[nodiscard]] CConfigDBHook RegisterHookAndCall(const CStr& name, std::function<void()> hook);
    183198
    184199    void UnregisterHook(CConfigDBHook&& hook);
     
    186201
    187202private:
    188     static std::map<CStr, CConfigValueSet> m_Map[];
    189     static std::multimap<CStr, std::function<void()>> m_Hooks;
    190     static VfsPath m_ConfigFile[];
    191     static bool m_HasChanges[];
     203    std::array<std::map<CStr, CConfigValueSet>, CFG_LAST> m_Map;
     204    std::multimap<CStr, std::function<void()>> m_Hooks;
     205    std::array<VfsPath, CFG_LAST> m_ConfigFile;
     206    std::array<bool, CFG_LAST> m_HasChanges;
     207
     208    mutable std::recursive_mutex m_Mutex;
    192209};
    193210
     
    197214public:
    198215    CConfigDBHook() = delete;
     216
    199217    // Point the moved-from hook to end, which is checked for in UnregisterHook,
    200218    // to avoid a double-erase error.
    201     CConfigDBHook(CConfigDBHook&& h) : m_ConfigDB(h.m_ConfigDB) { m_Ptr = std::move(h.m_Ptr); h.m_Ptr = m_ConfigDB.m_Hooks.end(); }
    202     CConfigDBHook(const CConfigDBHook&) = delete;
     219    CConfigDBHook(CConfigDBHook&& h) : m_ConfigDB(h.m_ConfigDB)
     220    {
     221        m_Ptr = std::move(h.m_Ptr);
     222        h.m_Ptr = m_ConfigDB.m_Hooks.end();
     223    }
     224    // Unregisters the hook. Must be called before the original ConfigDB gets deleted.
     225    ~CConfigDBHook()
     226    {
     227        m_ConfigDB.UnregisterHook(std::move(*this));
     228    }
    203229private:
    204     CConfigDBHook(CConfigDB& cdb, std::multimap<CStr, std::function<void()>>::iterator p) : m_ConfigDB(cdb), m_Ptr(p) {};
     230    CConfigDBHook(CConfigDB& cdb, std::multimap<CStr, std::function<void()>>::iterator p)
     231        : m_ConfigDB(cdb), m_Ptr(p)
     232    {};
    205233
    206234    std::multimap<CStr, std::function<void()>>::iterator m_Ptr;
  • ps/trunk/source/ps/GameSetup/Config.cpp

    r23747 r25326  
    1 /* Copyright (C) 2020 Wildfire Games.
     1/* Copyright (C) 202 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
     
    127127    TIMER(L"CONFIG_Init");
    128128
    129     new CConfigDB;
     129    ;
    130130
    131131    // Load the global, default config file
  • ps/trunk/source/ps/GameSetup/GameSetup.cpp

    r25231 r25326  
    720720from_config:
    721721    TIMER_BEGIN(L"shutdown ConfigDB");
    722     delete &g_ConfigDB;
     722    ;
    723723    TIMER_END(L"shutdown ConfigDB");
    724724
  • ps/trunk/source/ps/Joystick.cpp

    r17470 r25326  
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 20 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
     
    3434{
    3535    bool joystickEnable = false;
     36
     37
    3638    CFG_GET_VAL("joystick.enable", joystickEnable);
    3739    if (!joystickEnable)
  • ps/trunk/source/ps/tests/test_ConfigDB.h

    r25107 r25326  
    2121#include "ps/ConfigDB.h"
    2222
     23
     24
    2325extern PIVFS g_VFS;
    2426
    2527class TestConfigDB : public CxxTest::TestSuite
    2628{
    27     CConfigDB* configDB;
     29    configDB;
    2830public:
    2931
     
    3335        TS_ASSERT_OK(g_VFS->Mount(L"config", DataDir() / "_testconfig" / ""));
    3436
    35         configDB = new CConfigDB;
     37        configDB = ;
    3638    }
    3739
     
    4042        DeleteDirectory(DataDir()/"_testconfig");
    4143        g_VFS.reset();
    42 
    43         delete configDB;
     44        configDB.reset();
    4445    }
    4546
  • ps/trunk/source/ps/tests/test_Hotkeys.h

    r25180 r25326  
    3232class TestHotkey : public CxxTest::TestSuite
    3333{
    34     CConfigDB* configDB;
     34    configDB;
    3535    // Stores whether one of these was sent in the last fakeInput call.
    3636    bool hotkeyPress = false;
     
    6565        TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / ""));
    6666
    67         configDB = new CConfigDB;
     67        configDB = ;
    6868
    6969        g_scancodes = {};
     
    7272    void tearDown()
    7373    {
    74         delete configDB;
     74        ;
    7575        g_VFS.reset();
    7676        DeleteDirectory(DataDir()/"_testcache");
  • ps/trunk/source/renderer/RenderingOptions.cpp

    r25210 r25326  
    186186void CRenderingOptions::ClearHooks()
    187187{
    188     if (CConfigDB::IsInitialised())
    189         for (CConfigDBHook& hook : *m_ConfigHooks)
    190             g_ConfigDB.UnregisterHook(std::move(hook));
    191188    m_ConfigHooks->clear();
    192189}
  • ps/trunk/source/renderer/RenderingOptions.h

    r24651 r25326  
    2828#define INCLUDED_RENDERINGOPTIONS
    2929
     30
    3031class CStr8;
    3132class CRenderer;
Note: See TracChangeset for help on using the changeset viewer.