diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-04 02:28:48 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-04 02:28:48 -0400 |
commit | 43f87b4bcaa6d160cf7c4856109af06ea4873cf3 (patch) | |
tree | 8b04cd91eb747ddef40ce6e2db2e1efda7ff4ba4 | |
parent | bbe36a8246041544d6ebe420dfa1b695b6c74521 (diff) | |
download | abaddon-portaudio-43f87b4bcaa6d160cf7c4856109af06ea4873cf3.tar.gz abaddon-portaudio-43f87b4bcaa6d160cf7c4856109af06ea4873cf3.zip |
allow limiting concurrent http requests
add Semaphore
update SettingsManager a little
-rw-r--r-- | abaddon.cpp | 6 | ||||
-rw-r--r-- | abaddon.hpp | 2 | ||||
-rw-r--r-- | filecache.cpp | 18 | ||||
-rw-r--r-- | filecache.hpp | 3 | ||||
-rw-r--r-- | settings.cpp | 6 | ||||
-rw-r--r-- | settings.hpp | 14 | ||||
-rw-r--r-- | util.hpp | 27 |
7 files changed, 67 insertions, 9 deletions
diff --git a/abaddon.cpp b/abaddon.cpp index 0f8a679..2c8a839 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -85,7 +85,7 @@ int Abaddon::StartGTK() { } void Abaddon::LoadFromSettings() { - std::string token = m_settings.GetSetting("discord", "token"); + std::string token = m_settings.GetSettingString("discord", "token"); if (token.size()) { m_discord_token = token; m_discord.UpdateToken(m_discord_token); @@ -150,6 +150,10 @@ void Abaddon::DiscordOnGuildDelete(Snowflake guild_id) { m_main_window->UpdateChannelListing(); } +const SettingsManager &Abaddon::GetSettings() const { + return m_settings; +} + void Abaddon::ActionConnect() { if (!m_discord.IsStarted()) StartDiscord(); diff --git a/abaddon.hpp b/abaddon.hpp index 96728c6..3ca4151 100644 --- a/abaddon.hpp +++ b/abaddon.hpp @@ -61,6 +61,8 @@ public: void DiscordOnGuildCreate(Snowflake guild_id); void DiscordOnGuildDelete(Snowflake guild_id); + const SettingsManager &GetSettings() const; + private: DiscordClient m_discord; std::string m_discord_token; diff --git a/filecache.cpp b/filecache.cpp index f89bb3f..9e4b0b4 100644 --- a/filecache.cpp +++ b/filecache.cpp @@ -1,5 +1,8 @@ +#include "abaddon.hpp" #include "filecache.hpp" +constexpr static const int MaxConcurrentCacheHTTP = 10; + Cache::Cache() { m_tmp_path = std::filesystem::temp_directory_path() / "abaddon-cache"; std::filesystem::create_directories(m_tmp_path); @@ -29,16 +32,25 @@ void Cache::RespondFromPath(std::filesystem::path path, callback_type cb) { void Cache::GetFileFromURL(std::string url, callback_type cb) { auto cache_path = m_tmp_path / SanitizeString(url); if (std::filesystem::exists(cache_path)) { - m_futures.push_back(std::async(std::launch::async, [this, cache_path, cb]() { - RespondFromPath(cache_path, cb); })); + m_futures.push_back(std::async(std::launch::async, [this, cache_path, cb]() { RespondFromPath(cache_path, cb); })); return; } + // needs to be initialized like this or else ::Get() is called recursively + if (!m_semaphore) + m_semaphore = std::make_unique<Semaphore>(Abaddon::Get().GetSettings().GetSettingInt("http", "concurrent", MaxConcurrentCacheHTTP)); + if (m_callbacks.find(url) != m_callbacks.end()) { m_callbacks[url].push_back(cb); } else { - m_futures.push_back(cpr::GetCallback(std::bind(&Cache::OnResponse, this, std::placeholders::_1), cpr::Url { url })); m_callbacks[url].push_back(cb); + auto future = std::async(std::launch::async, [this, url]() { + m_semaphore->wait(); + const auto &r = cpr::Get(cpr::Url { url }); + m_semaphore->notify(); + OnResponse(r); + }); + m_futures.push_back(std::move(future)); } } diff --git a/filecache.hpp b/filecache.hpp index b54f842..eed355a 100644 --- a/filecache.hpp +++ b/filecache.hpp @@ -5,6 +5,7 @@ #include <filesystem> #include <vector> #include <unordered_map> +#include "util.hpp" // todo throttle requests and keep track of active requests to stop redundant requests @@ -23,6 +24,8 @@ private: void RespondFromPath(std::filesystem::path path, callback_type cb); void OnResponse(const cpr::Response &r); + std::unique_ptr<Semaphore> m_semaphore; + std::unordered_map<std::string, std::vector<callback_type>> m_callbacks; std::vector<std::future<void>> m_futures; std::filesystem::path m_tmp_path; diff --git a/settings.cpp b/settings.cpp index 494f1ba..daff887 100644 --- a/settings.cpp +++ b/settings.cpp @@ -14,12 +14,12 @@ SettingsManager::SettingsManager(std::string filename) m_ok = rc == SI_OK; } -std::string SettingsManager::GetSetting(std::string section, std::string key, std::string fallback) { +std::string SettingsManager::GetSettingString(std::string section, std::string key, std::string fallback) const { return m_ini.GetValue(section.c_str(), key.c_str(), fallback.c_str()); } -void SettingsManager::SetSetting(std::string section, std::string key, std::string value) { - m_ini.SetValue(section.c_str(), key.c_str(), value.c_str()); +int SettingsManager::GetSettingInt(std::string section, std::string key, int fallback) const { + return std::stoul(GetSettingString(section, key, std::to_string(fallback))); } bool SettingsManager::IsValid() const { diff --git a/settings.hpp b/settings.hpp index e6a5b99..7c914f4 100644 --- a/settings.hpp +++ b/settings.hpp @@ -1,5 +1,6 @@ #pragma once #include <string> +#include <type_traits> #include <SimpleIni.h> class SettingsManager { @@ -7,8 +8,17 @@ public: SettingsManager(std::string filename); void Close(); - std::string GetSetting(std::string section, std::string key, std::string fallback = ""); - void SetSetting(std::string section, std::string key, std::string value); + std::string GetSettingString(std::string section, std::string key, std::string fallback = "") const; + int GetSettingInt(std::string section, std::string key, int fallback) const; + + template<typename T> + void SetSetting(std::string section, std::string key, T value) { + static_assert(std::is_convertible<T, std::string>::value); + if constexpr (std::is_same<T, std::string>::value) + m_ini.SetValue(section.c_str(), key.c_str(), value.c_str()); + else + m_ini.SetValue(section.c_str(), key.c_str(), std::to_string(value).c_str()); + } bool IsValid() const; private: @@ -8,7 +8,34 @@ #include <sstream> #include <string> #include <iomanip> +#include <regex> +#include <mutex> +#include <condition_variable> + +class Semaphore { +public: + Semaphore(int count = 0) + : m_count(count) {} + + inline void notify() { + std::unique_lock<std::mutex> lock(m_mutex); + m_count++; + lock.unlock(); + m_cv.notify_one(); + } + + inline void wait() { + std::unique_lock<std::mutex> lock(m_mutex); + while (m_count == 0) + m_cv.wait(lock); + m_count--; + } +private: + std::mutex m_mutex; + std::condition_variable m_cv; + int m_count; +}; // gtkmm doesnt seem to work #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN |