Skip to content

Commit 31e7257

Browse files
committed
⚡ Event-driven change detection
refs #35
1 parent fbd7ea1 commit 31e7257

File tree

6 files changed

+60
-33
lines changed

6 files changed

+60
-33
lines changed

src/APILayerStore.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// SPDX-License-Identifier: ISC
33

44
#pragma once
5+
#include <boost/signals2.hpp>
6+
57
#include <span>
68
#include <vector>
79

@@ -21,16 +23,27 @@ class APILayerStore {
2123
// e.g. if we're a 64-bit build, we won't see 32-bit layers
2224
virtual bool IsForCurrentArchitecture() const noexcept = 0;
2325

24-
virtual bool Poll() const noexcept = 0;
26+
virtual boost::signals2::scoped_connection OnChange(
27+
std::function<void()> callback) noexcept {
28+
return mOnChangeSignal.connect(std::move(callback));
29+
}
30+
31+
static std::span<APILayerStore*> Get() noexcept;
32+
33+
protected:
34+
void NotifyChange() {
35+
mOnChangeSignal();
36+
}
2537

26-
static std::span<const APILayerStore*> Get() noexcept;
38+
private:
39+
boost::signals2::signal<void()> mOnChangeSignal;
2740
};
2841

2942
class ReadWriteAPILayerStore : public virtual APILayerStore {
3043
public:
3144
virtual bool SetAPILayers(const std::vector<APILayer>&) const noexcept = 0;
3245

33-
static std::span<const ReadWriteAPILayerStore*> Get() noexcept;
46+
static std::span<ReadWriteAPILayerStore*> Get() noexcept;
3447
};
3548

3649
}// namespace FredEmmott::OpenXRLayers

src/GUI.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ void GUI::DrawFrame() {
5959
}
6060

6161
GUI::GUI() {
62+
const auto stores = ReadWriteAPILayerStore::Get();
63+
mLayerSets.reserve(stores.size());
6264
for (auto&& store: ReadWriteAPILayerStore::Get()) {
63-
mLayerSets.push_back({store});
65+
mLayerSets.emplace_back(store);
6466
}
6567
}
6668

@@ -69,6 +71,13 @@ void GUI::Run() {
6971
platform.GUIMain(std::bind_front(&GUI::DrawFrame, this));
7072
}
7173

74+
GUI::LayerSet::~LayerSet() = default;
75+
76+
GUI::LayerSet::LayerSet(ReadWriteAPILayerStore* store) : mStore(store) {
77+
mOnChangeConnection
78+
= store->OnChange([this] { this->mLayerDataIsStale = true; });
79+
}
80+
7281
void GUI::LayerSet::GUILayersList() {
7382
auto viewport = ImGui::GetMainViewport();
7483
const auto dpiScale = Platform::Get().GetDPIScaling();
@@ -632,9 +641,6 @@ void GUI::LayerSet::DragDropReorder(
632641
}
633642

634643
void GUI::LayerSet::Draw() {
635-
if (mStore->Poll()) {
636-
mLayerDataIsStale = true;
637-
}
638644
if (mLayerDataIsStale) {
639645
this->ReloadLayerDataNow();
640646
}

src/GUI.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#pragma once
55

6+
#include <boost/signals2/connection.hpp>
7+
68
#include <vector>
79

810
#include "APILayer.hpp"
@@ -20,8 +22,17 @@ class GUI final {
2022
private:
2123
using LintErrors = std::vector<std::shared_ptr<LintError>>;
2224

23-
class LayerSet {
25+
class LayerSet final {
2426
public:
27+
LayerSet() = delete;
28+
~LayerSet();
29+
explicit LayerSet(ReadWriteAPILayerStore* store);
30+
31+
LayerSet(const LayerSet&) = delete;
32+
LayerSet& operator=(const LayerSet&) = delete;
33+
LayerSet(LayerSet&&) = default;
34+
LayerSet& operator=(LayerSet&&) = default;
35+
2536
std::type_identity_t<const ReadWriteAPILayerStore>* mStore {nullptr};
2637

2738
std::vector<APILayer> mLayers;
@@ -51,6 +62,9 @@ class GUI final {
5162

5263
void AddLayersClicked();
5364
void DragDropReorder(const APILayer& source, const APILayer& target);
65+
66+
private:
67+
boost::signals2::scoped_connection mOnChangeConnection;
5468
};
5569

5670
std::vector<LayerSet> mLayerSets;

src/windows/WindowsAPILayerStore.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ WindowsAPILayerStore::WindowsAPILayerStore(
6262
mKey = {};
6363
return;
6464
}
65-
mEvent.reset(CreateEvent(nullptr, false, false, nullptr));
66-
this->WindowsAPILayerStore::Poll();
65+
66+
mWatcher = wil::make_registry_watcher(
67+
mKey.get(), /* no subkey. nullptr not allowed */ L"", true, [this](auto) {
68+
this->NotifyChange();
69+
});
6770
}
6871

6972
WindowsAPILayerStore::~WindowsAPILayerStore() = default;
@@ -136,13 +139,6 @@ std::vector<APILayer> WindowsAPILayerStore::GetAPILayers() const noexcept {
136139
return layers;
137140
}
138141

139-
bool WindowsAPILayerStore::Poll() const noexcept {
140-
const auto result = WaitForSingleObject(mEvent.get(), 0);
141-
RegNotifyChangeKeyValue(
142-
mKey.get(), false, REG_NOTIFY_CHANGE_LAST_SET, mEvent.get(), true);
143-
return (result == WAIT_OBJECT_0);
144-
}
145-
146142
class ReadOnlyWindowsAPILayerStore final : public WindowsAPILayerStore {
147143
public:
148144
ReadOnlyWindowsAPILayerStore(
@@ -229,26 +225,26 @@ class ReadWriteWindowsAPILayerStore final : public WindowsAPILayerStore,
229225
};
230226

231227
template <class TInterface, class TConcrete>
232-
std::span<const TInterface*> GetStaticStores() noexcept {
228+
std::span<TInterface*> GetStaticStores() noexcept {
233229
using RB = WindowsAPILayerStore::RegistryBitness;
234230
using enum APILayer::Kind;
235-
static const TConcrete sHKLM64 {
231+
static TConcrete sHKLM64 {
236232
"Win64-HKLM", Implicit, RB::Wow64_64, HKEY_LOCAL_MACHINE};
237-
static const TConcrete sHKCU64 {
233+
static TConcrete sHKCU64 {
238234
"Win64-HKCU", Implicit, RB::Wow64_64, HKEY_CURRENT_USER};
239-
static const TConcrete sHKLM32 {
235+
static TConcrete sHKLM32 {
240236
"Win32-HKLM", Implicit, RB::Wow64_32, HKEY_LOCAL_MACHINE};
241-
static const TConcrete sHKCU32 {
237+
static TConcrete sHKCU32 {
242238
"Win32-HKCU", Implicit, RB::Wow64_32, HKEY_CURRENT_USER};
243-
static const TConcrete sExplicitHKLM64 {
239+
static TConcrete sExplicitHKLM64 {
244240
"Explicit Win64-HKLM", Explicit, RB::Wow64_64, HKEY_LOCAL_MACHINE};
245-
static const TConcrete sExplicitHKCU64 {
241+
static TConcrete sExplicitHKCU64 {
246242
"Explicit Win64-HKCU", Explicit, RB::Wow64_64, HKEY_CURRENT_USER};
247-
static const TConcrete sExplicitHKLM32 {
243+
static TConcrete sExplicitHKLM32 {
248244
"Explicit Win32-HKLM", Explicit, RB::Wow64_32, HKEY_LOCAL_MACHINE};
249-
static const TConcrete sExplicitHKCU32 {
245+
static TConcrete sExplicitHKCU32 {
250246
"Explicit Win32-HKCU", Explicit, RB::Wow64_32, HKEY_CURRENT_USER};
251-
static const TInterface* sStores[] {
247+
static TInterface* sStores[] {
252248
&sHKLM64,
253249
&sHKCU64,
254250
&sHKLM32,
@@ -261,12 +257,11 @@ std::span<const TInterface*> GetStaticStores() noexcept {
261257
return sStores;
262258
}
263259

264-
std::span<const APILayerStore*> APILayerStore::Get() noexcept {
260+
std::span<APILayerStore*> APILayerStore::Get() noexcept {
265261
return GetStaticStores<APILayerStore, ReadOnlyWindowsAPILayerStore>();
266262
};
267263

268-
std::span<const ReadWriteAPILayerStore*>
269-
ReadWriteAPILayerStore::Get() noexcept {
264+
std::span<ReadWriteAPILayerStore*> ReadWriteAPILayerStore::Get() noexcept {
270265
return GetStaticStores<
271266
ReadWriteAPILayerStore,
272267
ReadWriteWindowsAPILayerStore>();

src/windows/WindowsAPILayerStore.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class WindowsAPILayerStore : public virtual APILayerStore {
2727

2828
std::vector<APILayer> GetAPILayers() const noexcept override;
2929

30-
bool Poll() const noexcept override;
31-
3230
bool IsForCurrentArchitecture() const noexcept override {
3331
return std::to_underlying(mRegistryBitness) == sizeof(void*);
3432
}
@@ -50,13 +48,13 @@ class WindowsAPILayerStore : public virtual APILayerStore {
5048
REGSAM desiredAccess);
5149

5250
wil::unique_hkey mKey {};
53-
wil::unique_event mEvent {};
5451

5552
private:
5653
const std::string mDisplayName;
5754
const APILayer::Kind mLayerKind;
5855
const RegistryBitness mRegistryBitness;
5956
const HKEY mRootKey;
57+
wil::unique_registry_watcher mWatcher;
6058
};
6159

6260
}// namespace FredEmmott::OpenXRLayers

vcpkg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"win32-binding"
1515
]
1616
},
17+
"boost-signals2",
1718
"nlohmann-json",
1819
"fmt",
1920
"openxr-loader"

0 commit comments

Comments
 (0)