Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/UWP/UWPHelpers/StorageAsync.h
5784 views
1
// Thanks to RetroArch/Libretro team for this idea
2
// This is improved version of the original idea
3
4
#pragma once
5
6
#include "pch.h"
7
#include <ppl.h>
8
#include <ppltasks.h>
9
#include <type_traits>
10
11
#include "Common/Log.h"
12
#include "UWPUtil.h"
13
14
// Helper to detect if a type is a WinRT runtime class (nullable)
15
template<typename T>
16
struct is_winrt_class : std::bool_constant<std::is_base_of_v<winrt::Windows::Foundation::IUnknown, T>> {};
17
18
// Execute a WinRT async operation synchronously by spinning the message pump (for WinRT classes)
19
template<typename T>
20
T ExecuteAsyncWithPump(winrt::Windows::Foundation::IAsyncOperation<T> asyncOp)
21
{
22
T result{ nullptr };
23
bool done = false;
24
25
asyncOp.Completed([&](auto&& sender, winrt::Windows::Foundation::AsyncStatus status) {
26
if (status == winrt::Windows::Foundation::AsyncStatus::Completed) {
27
try {
28
result = sender.GetResults();
29
}
30
catch (const winrt::hresult_error& e) {
31
ERROR_LOG(Log::FileSystem, "%s", winrt::to_string(e.message()).c_str());
32
}
33
}
34
done = true;
35
});
36
37
winrt::Windows::UI::Core::CoreWindow corewindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread();
38
while (!done)
39
{
40
try {
41
if (corewindow) {
42
corewindow.Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
43
}
44
else {
45
corewindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread();
46
}
47
}
48
catch (...) {
49
50
}
51
}
52
53
return result;
54
}
55
56
// Execute for value types with default value
57
template<typename T>
58
T ExecuteAsyncWithPumpValue(winrt::Windows::Foundation::IAsyncOperation<T> asyncOp, T def)
59
{
60
T result = def;
61
bool done = false;
62
63
asyncOp.Completed([&](auto&& sender, winrt::Windows::Foundation::AsyncStatus status) {
64
if (status == winrt::Windows::Foundation::AsyncStatus::Completed) {
65
try {
66
result = sender.GetResults();
67
}
68
catch (const winrt::hresult_error& e) {
69
ERROR_LOG(Log::FileSystem, "%s", winrt::to_string(e.message()).c_str());
70
}
71
}
72
done = true;
73
});
74
75
winrt::Windows::UI::Core::CoreWindow corewindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread();
76
while (!done)
77
{
78
try {
79
if (corewindow) {
80
corewindow.Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
81
}
82
else {
83
corewindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread();
84
}
85
}
86
catch (...) {
87
88
}
89
}
90
91
return result;
92
}
93
94
bool ActionPass(winrt::Windows::Foundation::IAsyncAction action);
95
96
// ExecuteTask for WinRT runtime class types (StorageFile, StorageFolder, etc)
97
template<typename T, std::enable_if_t<is_winrt_class<T>::value, int> = 0>
98
void ExecuteTask(T& out, winrt::Windows::Foundation::IAsyncOperation<T> task)
99
{
100
try {
101
out = ExecuteAsyncWithPump<T>(task);
102
}
103
catch (...) {
104
out = nullptr;
105
}
106
}
107
108
// ExecuteTask for value types (bool, int, enums, etc)
109
template<typename T, std::enable_if_t<!is_winrt_class<T>::value, int> = 0>
110
void ExecuteTask(T& out, winrt::Windows::Foundation::IAsyncOperation<T> task)
111
{
112
try {
113
out = ExecuteAsyncWithPumpValue<T>(task, T{});
114
}
115
catch (...) {
116
out = T{};
117
}
118
}
119
120
// ExecuteTask for value types with default value
121
template<typename T>
122
void ExecuteTask(T& out, winrt::Windows::Foundation::IAsyncOperation<T> task, T def)
123
{
124
try {
125
out = ExecuteAsyncWithPumpValue<T>(task, def);
126
}
127
catch (...) {
128
out = def;
129
}
130
}
131
132
// Async action such as 'Delete' file
133
// @action: async action
134
// return false when action failed
135
bool ExecuteTask(winrt::Windows::Foundation::IAsyncAction action);
136
137