diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2016-08-10 16:54:06 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2016-08-10 16:54:06 +0200 |
commit | 28ab0947c7fbf4224ece0d902be9f946807015d8 (patch) | |
tree | 5730670e1ae6f58334c05718cc414045d92e5696 /opentrack-dinput/dinput.cpp | |
parent | cdacaf690a48a3cc1549d9c6e57de2100dc1fc21 (diff) |
dinput: prevent freeing handle despite static initializer order
Diffstat (limited to 'opentrack-dinput/dinput.cpp')
-rw-r--r-- | opentrack-dinput/dinput.cpp | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/opentrack-dinput/dinput.cpp b/opentrack-dinput/dinput.cpp index ce80fe0e..06b5e4f2 100644 --- a/opentrack-dinput/dinput.cpp +++ b/opentrack-dinput/dinput.cpp @@ -3,22 +3,11 @@ #include "dinput.hpp" #include <QDebug> -dinput_handle dinput_handle::self; +std::atomic<int> dinput_handle::refcnt; +std::atomic_flag dinput_handle::init_lock = ATOMIC_FLAG_INIT; +dinput_handle::di_t dinput_handle::handle(dinput_handle::make_di()); -dinput_handle::dinput_handle() : handle(init_di()) -{ -} - -dinput_handle::~dinput_handle() -{ - if (handle) - { - handle->Release(); - handle = nullptr; - } -} - -dinput_handle::di_t dinput_handle::init_di() +LPDIRECTINPUT8& dinput_handle::init_di() { HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) @@ -27,13 +16,9 @@ dinput_handle::di_t dinput_handle::init_di() static LPDIRECTINPUT8 di_ = nullptr; if (di_ == nullptr) { - if (SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di_, NULL))) - { - return di_; - } - else + if (!SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di_, NULL))) { - return di_ = nullptr; + di_ = nullptr; } } return di_; @@ -41,7 +26,44 @@ dinput_handle::di_t dinput_handle::init_di() dinput_handle::di_t dinput_handle::make_di() { - return self.handle; + while (init_lock.test_and_set()) { /* busy loop */ } + + LPDIRECTINPUT8& ret = init_di(); + + init_lock.clear(); + + return di_t(ret); } #endif + +dinput_handle::di_t::di_t(LPDIRECTINPUT8& handle) : handle(handle) +{ + while (init_lock.test_and_set()) { /* busy loop */ } + + refcnt++; + + init_lock.clear(); +} + +void dinput_handle::di_t::free_di() +{ + if (handle) + handle->Release(); + handle = nullptr; +} + +dinput_handle::di_t::~di_t() +{ + while (init_lock.test_and_set()) { /* busy loop */ } + + int refcnt_ = refcnt.fetch_sub(1); + + if (refcnt_ == 1) + { + qDebug() << "exit: deleting di handle"; + free_di(); + } + + init_lock.clear(); +} |