diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/common/detached_tasks.cpp | 41 | ||||
| -rw-r--r-- | src/common/detached_tasks.h | 40 | ||||
| -rw-r--r-- | src/common/logging/text_formatter.cpp | 2 | ||||
| -rw-r--r-- | src/common/param_package.cpp | 18 | ||||
| -rw-r--r-- | src/common/param_package.h | 2 | ||||
| -rw-r--r-- | src/common/web_result.h | 24 |
7 files changed, 129 insertions, 3 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 6a3f1fe08..d0e506689 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -29,7 +29,7 @@ if ($ENV{CI}) | |||
| 29 | if (BUILD_VERSION) | 29 | if (BUILD_VERSION) |
| 30 | # This leaves a trailing space on the last word, but we actually want that | 30 | # This leaves a trailing space on the last word, but we actually want that |
| 31 | # because of how it's styled in the title bar. | 31 | # because of how it's styled in the title bar. |
| 32 | set(BUILD_FULLNAME "${REPO_NAME} #${BUILD_VERSION} ") | 32 | set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") |
| 33 | else() | 33 | else() |
| 34 | set(BUILD_FULLNAME "") | 34 | set(BUILD_FULLNAME "") |
| 35 | endif() | 35 | endif() |
| @@ -41,6 +41,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU | |||
| 41 | add_library(common STATIC | 41 | add_library(common STATIC |
| 42 | alignment.h | 42 | alignment.h |
| 43 | assert.h | 43 | assert.h |
| 44 | detached_tasks.cpp | ||
| 45 | detached_tasks.h | ||
| 44 | bit_field.h | 46 | bit_field.h |
| 45 | bit_set.h | 47 | bit_set.h |
| 46 | cityhash.cpp | 48 | cityhash.cpp |
| @@ -87,6 +89,7 @@ add_library(common STATIC | |||
| 87 | timer.cpp | 89 | timer.cpp |
| 88 | timer.h | 90 | timer.h |
| 89 | vector_math.h | 91 | vector_math.h |
| 92 | web_result.h | ||
| 90 | ) | 93 | ) |
| 91 | 94 | ||
| 92 | if(ARCHITECTURE_x86_64) | 95 | if(ARCHITECTURE_x86_64) |
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp new file mode 100644 index 000000000..a347d9e02 --- /dev/null +++ b/src/common/detached_tasks.cpp | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <thread> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/detached_tasks.h" | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | DetachedTasks* DetachedTasks::instance = nullptr; | ||
| 12 | |||
| 13 | DetachedTasks::DetachedTasks() { | ||
| 14 | ASSERT(instance == nullptr); | ||
| 15 | instance = this; | ||
| 16 | } | ||
| 17 | |||
| 18 | void DetachedTasks::WaitForAllTasks() { | ||
| 19 | std::unique_lock<std::mutex> lock(mutex); | ||
| 20 | cv.wait(lock, [this]() { return count == 0; }); | ||
| 21 | } | ||
| 22 | |||
| 23 | DetachedTasks::~DetachedTasks() { | ||
| 24 | std::unique_lock<std::mutex> lock(mutex); | ||
| 25 | ASSERT(count == 0); | ||
| 26 | instance = nullptr; | ||
| 27 | } | ||
| 28 | |||
| 29 | void DetachedTasks::AddTask(std::function<void()> task) { | ||
| 30 | std::unique_lock<std::mutex> lock(instance->mutex); | ||
| 31 | ++instance->count; | ||
| 32 | std::thread([task{std::move(task)}]() { | ||
| 33 | task(); | ||
| 34 | std::unique_lock<std::mutex> lock(instance->mutex); | ||
| 35 | --instance->count; | ||
| 36 | std::notify_all_at_thread_exit(instance->cv, std::move(lock)); | ||
| 37 | }) | ||
| 38 | .detach(); | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace Common | ||
diff --git a/src/common/detached_tasks.h b/src/common/detached_tasks.h new file mode 100644 index 000000000..5dd8fc27b --- /dev/null +++ b/src/common/detached_tasks.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <condition_variable> | ||
| 8 | #include <functional> | ||
| 9 | |||
| 10 | namespace Common { | ||
| 11 | |||
| 12 | /** | ||
| 13 | * A background manager which ensures that all detached task is finished before program exits. | ||
| 14 | * | ||
| 15 | * Some tasks, telemetry submission for example, prefer executing asynchronously and don't care | ||
| 16 | * about the result. These tasks are suitable for std::thread::detach(). However, this is unsafe if | ||
| 17 | * the task is launched just before the program exits (which is a common case for telemetry), so we | ||
| 18 | * need to block on these tasks on program exit. | ||
| 19 | * | ||
| 20 | * To make detached task safe, a single DetachedTasks object should be placed in the main(), and | ||
| 21 | * call WaitForAllTasks() after all program execution but before global/static variable destruction. | ||
| 22 | * Any potentially unsafe detached task should be executed via DetachedTasks::AddTask. | ||
| 23 | */ | ||
| 24 | class DetachedTasks { | ||
| 25 | public: | ||
| 26 | DetachedTasks(); | ||
| 27 | ~DetachedTasks(); | ||
| 28 | void WaitForAllTasks(); | ||
| 29 | |||
| 30 | static void AddTask(std::function<void()> task); | ||
| 31 | |||
| 32 | private: | ||
| 33 | static DetachedTasks* instance; | ||
| 34 | |||
| 35 | std::condition_variable cv; | ||
| 36 | std::mutex mutex; | ||
| 37 | int count = 0; | ||
| 38 | }; | ||
| 39 | |||
| 40 | } // namespace Common | ||
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp index 05437c137..6a0605c63 100644 --- a/src/common/logging/text_formatter.cpp +++ b/src/common/logging/text_formatter.cpp | |||
| @@ -31,7 +31,7 @@ std::string FormatLogMessage(const Entry& entry) { | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | void PrintMessage(const Entry& entry) { | 33 | void PrintMessage(const Entry& entry) { |
| 34 | auto str = FormatLogMessage(entry) + '\n'; | 34 | const auto str = FormatLogMessage(entry).append(1, '\n'); |
| 35 | fputs(str.c_str(), stderr); | 35 | fputs(str.c_str(), stderr); |
| 36 | } | 36 | } |
| 37 | 37 | ||
diff --git a/src/common/param_package.cpp b/src/common/param_package.cpp index 9526ca0c6..b916b4866 100644 --- a/src/common/param_package.cpp +++ b/src/common/param_package.cpp | |||
| @@ -20,7 +20,15 @@ constexpr char KEY_VALUE_SEPARATOR_ESCAPE[] = "$0"; | |||
| 20 | constexpr char PARAM_SEPARATOR_ESCAPE[] = "$1"; | 20 | constexpr char PARAM_SEPARATOR_ESCAPE[] = "$1"; |
| 21 | constexpr char ESCAPE_CHARACTER_ESCAPE[] = "$2"; | 21 | constexpr char ESCAPE_CHARACTER_ESCAPE[] = "$2"; |
| 22 | 22 | ||
| 23 | /// A placeholder for empty param packages to avoid empty strings | ||
| 24 | /// (they may be recognized as "not set" by some frontend libraries like qt) | ||
| 25 | constexpr char EMPTY_PLACEHOLDER[] = "[empty]"; | ||
| 26 | |||
| 23 | ParamPackage::ParamPackage(const std::string& serialized) { | 27 | ParamPackage::ParamPackage(const std::string& serialized) { |
| 28 | if (serialized == EMPTY_PLACEHOLDER) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 24 | std::vector<std::string> pairs; | 32 | std::vector<std::string> pairs; |
| 25 | Common::SplitString(serialized, PARAM_SEPARATOR, pairs); | 33 | Common::SplitString(serialized, PARAM_SEPARATOR, pairs); |
| 26 | 34 | ||
| @@ -46,7 +54,7 @@ ParamPackage::ParamPackage(std::initializer_list<DataType::value_type> list) : d | |||
| 46 | 54 | ||
| 47 | std::string ParamPackage::Serialize() const { | 55 | std::string ParamPackage::Serialize() const { |
| 48 | if (data.empty()) | 56 | if (data.empty()) |
| 49 | return ""; | 57 | return EMPTY_PLACEHOLDER; |
| 50 | 58 | ||
| 51 | std::string result; | 59 | std::string result; |
| 52 | 60 | ||
| @@ -120,4 +128,12 @@ bool ParamPackage::Has(const std::string& key) const { | |||
| 120 | return data.find(key) != data.end(); | 128 | return data.find(key) != data.end(); |
| 121 | } | 129 | } |
| 122 | 130 | ||
| 131 | void ParamPackage::Erase(const std::string& key) { | ||
| 132 | data.erase(key); | ||
| 133 | } | ||
| 134 | |||
| 135 | void ParamPackage::Clear() { | ||
| 136 | data.clear(); | ||
| 137 | } | ||
| 138 | |||
| 123 | } // namespace Common | 139 | } // namespace Common |
diff --git a/src/common/param_package.h b/src/common/param_package.h index 7842cd4ef..6a0a9b656 100644 --- a/src/common/param_package.h +++ b/src/common/param_package.h | |||
| @@ -32,6 +32,8 @@ public: | |||
| 32 | void Set(const std::string& key, int value); | 32 | void Set(const std::string& key, int value); |
| 33 | void Set(const std::string& key, float value); | 33 | void Set(const std::string& key, float value); |
| 34 | bool Has(const std::string& key) const; | 34 | bool Has(const std::string& key) const; |
| 35 | void Erase(const std::string& key); | ||
| 36 | void Clear(); | ||
| 35 | 37 | ||
| 36 | private: | 38 | private: |
| 37 | DataType data; | 39 | DataType data; |
diff --git a/src/common/web_result.h b/src/common/web_result.h new file mode 100644 index 000000000..969926674 --- /dev/null +++ b/src/common/web_result.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | struct WebResult { | ||
| 11 | enum class Code : u32 { | ||
| 12 | Success, | ||
| 13 | InvalidURL, | ||
| 14 | CredentialsMissing, | ||
| 15 | LibError, | ||
| 16 | HttpError, | ||
| 17 | WrongContent, | ||
| 18 | NoWebservice, | ||
| 19 | }; | ||
| 20 | Code result_code; | ||
| 21 | std::string result_string; | ||
| 22 | std::string returned_data; | ||
| 23 | }; | ||
| 24 | } // namespace Common | ||