diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a834fb..ef1c8fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,31 +6,24 @@ set(CMAKE_CXX_STANDARD 20) find_package(PkgConfig REQUIRED) find_package(nlohmann_json REQUIRED) -find_package(Boost 1.70 COMPONENTS thread REQUIRED) +find_package(folly REQUIRED) pkg_check_modules(GTKMM REQUIRED gtkmm-4.0) pkg_check_modules(GLIBMM REQUIRED glibmm-2.68) pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4) -pkg_check_modules(LIBADWAITA REQUIRED libadwaita-1) +#pkg_check_modules(LIBADWAITA REQUIRED libadwaita-1) include_directories(${GTKMM_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} - ${LIBSOUP_INCLUDE_DIRS} - ${Boost_INCLUDE_DIR} - ${LIBADWAITA_INCLUDE_DIRS}) + ${LIBSOUP_INCLUDE_DIRS}) link_directories(${GTKMM_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} - ${LIBSOUP_LIBRARY_DIRS} - ${Boost_LIBRARY_DIRS} - ${LIBADWAITA_LIBRARY_DIRS}) + ${LIBSOUP_LIBRARY_DIRS}) -add_definitions(-DBOOST_THREAD_PROVIDES_FUTURE -DBOOST_THREAD_PROVIDES_FUTURE_CONTINUATION -DBOOST_THREAD_PROVIDES_PROMISE_LAZY -DBOOST_THREAD_VERSION=4) - -add_executable(autocat_gnome main.cpp gui/MainWindow.cpp gui/MainWindow.h gui/LoginWindow.cpp gui/LoginWindow.h services/Api.cpp services/Api.h coro/Task.h models/User.cpp models/User.h services/Settings.cpp services/Settings.h app/App.cpp app/App.h gui/TitleBar.cpp gui/TitleBar.h) +add_executable(autocat_gnome main.cpp gui/MainWindow.cpp gui/MainWindow.h gui/LoginWindow.cpp gui/LoginWindow.h services/Api.cpp services/Api.h models/User.cpp models/User.h services/Settings.cpp services/Settings.h gui/TitleBar.cpp gui/TitleBar.h coro/Coro.h) target_link_libraries(autocat_gnome ${GTKMM_LIBRARIES} ${GLIBMM_LIBRARIES} ${LIBSOUP_LIBRARIES} nlohmann_json::nlohmann_json - ${Boost_LIBRARIES} - ${LIBADWAITA_LIBRARIES}) + Folly::folly) diff --git a/app/App.cpp b/app/App.cpp deleted file mode 100644 index f60a34a..0000000 --- a/app/App.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by selim on 02.02.2022. -// - -#include "App.h" -#include "../gui/MainWindow.h" - -static void activateApp(GtkApplication *gtkApp, void* data) { - auto app = reinterpret_cast(data); - - int i = 0; - - auto win = std::make_shared(); - app->setWindow(win); - -// GtkWidget *window = gtk_application_window_new (gtkApp); -// GtkWidget *label = gtk_label_new ("Hello World"); -// -// gtk_window_set_title (GTK_WINDOW (window), "Hello"); -// gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); -// gtk_window_set_child (GTK_WINDOW (window), label); -// gtk_window_present (GTK_WINDOW (window)); -} - -App::App(): _app(nullptr), _window(nullptr) { - _app = adw_application_new("pro.aliencat.aliencat", G_APPLICATION_FLAGS_NONE); - g_signal_connect_data(_app, "activate", G_CALLBACK(activateApp), this, nullptr, G_CONNECT_AFTER); -} - -App::~App() { - glib_autoptr_cleanup_AdwApplication(&_app); -} - -int App::run(int argc, char **argv) { - return g_application_run(G_APPLICATION(_app), argc, argv); -} - -void App::setWindow(std::shared_ptr window) { - gtk_application_add_window(GTK_APPLICATION(_app), window->gobj()); - - if(_window) { - _window->hide(); - gtk_application_remove_window(GTK_APPLICATION(_app), _window->gobj()); - } - - window->show(); - _window = window; -} diff --git a/app/App.h b/app/App.h deleted file mode 100644 index 7846f25..0000000 --- a/app/App.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by selim on 02.02.2022. -// - -#ifndef AUTOCAT_GNOME_APP_H -#define AUTOCAT_GNOME_APP_H - -#include -#include -#include - -class App { -private: - AdwApplication* _app; - std::shared_ptr _window; - -public: - explicit App(); - ~App(); - int run(int argc, char** argv); - void setWindow(std::shared_ptr window); -}; - - -#endif //AUTOCAT_GNOME_APP_H diff --git a/coro/Coro.h b/coro/Coro.h new file mode 100644 index 0000000..48922c7 --- /dev/null +++ b/coro/Coro.h @@ -0,0 +1,36 @@ +// +// Created by selim on 20.04.2022. +// + +#ifndef AUTOCAT_GNOME_CORO_H +#define AUTOCAT_GNOME_CORO_H + +#include +#include +#include + +template +struct std::coroutine_traits { + struct promise_type { + void get_return_object() noexcept {} + + std::suspend_never initial_suspend() const noexcept { + return {}; + } + std::suspend_never final_suspend() const noexcept { + return {}; + } + + void return_void() noexcept {} + + void unhandled_exception() noexcept { + try { + std::rethrow_exception(std::current_exception()); + } catch (std::exception& ex) { + std::cout << "Unhandled exception (in void coroutine) detected: " << ex.what() << std::endl; + } + } + }; +}; + +#endif //AUTOCAT_GNOME_CORO_H diff --git a/coro/Task.h b/coro/Task.h deleted file mode 100644 index 428b127..0000000 --- a/coro/Task.h +++ /dev/null @@ -1,147 +0,0 @@ -// -// Created by selim on 03.01.2022. -// - -#ifndef AUTOCAT_GNOME_TASK_H -#define AUTOCAT_GNOME_TASK_H - -#include -#include -#include -#include - -#include -#include -#include -#include - -class FutureException: public virtual std::exception, public virtual boost::exception { -private: - std::string _message; - -public: - explicit FutureException(const char* msg): _message(msg) {} - explicit FutureException(std::string msg): _message(std::move(msg)) {} - - const char* what() const noexcept { - return _message.c_str(); - } -}; - -// Enable the use of std::future as a coroutine type -// by using a std::promise as the promise type. -template -requires(!std::is_void_v && !std::is_reference_v) -struct std::coroutine_traits, Args...> { - struct promise_type : boost::promise { - boost::future get_return_object() noexcept { - return this->get_future(); - } - - std::suspend_never initial_suspend() const noexcept { - return {}; - } - std::suspend_never final_suspend() const noexcept { - return {}; - } - - void return_value(const T &value) - noexcept(std::is_nothrow_copy_constructible_v) { - this->set_value(value); - } - void return_value(T &&value) - noexcept(std::is_nothrow_move_constructible_v) { - this->set_value(std::move(value)); - } - void unhandled_exception() noexcept { - this->set_exception(boost::current_exception()); - } - }; -}; - -// Same for std::future. -template -struct std::coroutine_traits, Args...> { - struct promise_type : boost::promise { - boost::future get_return_object() noexcept { - return this->get_future(); - } - - std::suspend_never initial_suspend() const noexcept { - return {}; - } - std::suspend_never final_suspend() const noexcept { - return {}; - } - - void return_void() noexcept { - this->set_value(); - } - void unhandled_exception() noexcept { - this->set_exception(boost::current_exception()); - } - }; -}; - -template -struct std::coroutine_traits { - struct promise_type { - void get_return_object() noexcept {} - - std::suspend_never initial_suspend() const noexcept { - return {}; - } - std::suspend_never final_suspend() const noexcept { - return {}; - } - - void return_void() noexcept {} - - void unhandled_exception() noexcept { - try { - boost::rethrow_exception(boost::current_exception()); - } catch (std::exception& ex) { - std::cout << "Unhandled exception (in void coroutine) detected: " << ex.what() << std::endl; - } - } - }; -}; - -template -auto operator co_await(boost::future future) noexcept requires(!std::is_reference_v) { - - struct awaiter : public boost::future { - - bool await_ready() const noexcept { - return this->is_ready(); - } - void await_suspend(std::coroutine_handle<> cont) { - this->then([this, cont](boost::future&& fut){ - - // future was moved out of awaiter to this lambda - // so, we need to bring it back - this->swap(fut); - - // Resume coroutine on the main thread (i.e. GMainContext) - g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, awaiter::resumeContinuation, (gpointer)&cont, nullptr); - }); - } - - T await_resume() { - return this->get(); - } - - static int resumeContinuation(void* data) { - auto handler = reinterpret_cast*>(data); - if(*handler) { - handler->resume(); - } - - return G_SOURCE_REMOVE; - } - }; - - return awaiter{std::move(future)}; -} - -#endif //AUTOCAT_GNOME_TASK_H \ No newline at end of file diff --git a/gui/LoginWindow.cpp b/gui/LoginWindow.cpp index e7591e6..a09b088 100644 --- a/gui/LoginWindow.cpp +++ b/gui/LoginWindow.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include LoginWindow::LoginWindow() { set_title("Login"); @@ -48,7 +50,7 @@ void LoginWindow::loginClicked() { _spinner.start(); try { - auto user = co_await Api::login(email, password); + User user = co_await Api::login(email, password).scheduleOn(folly::getGlobalIOExecutor()); auto app = this->get_application(); auto mainWindow = new MainWindow(); mainWindow->show(); diff --git a/main.cpp b/main.cpp index 6e66506..278b798 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,6 @@ #include "gui/MainWindow.h" #include "gui/LoginWindow.h" #include "services/Settings.h" -#include "app/App.h" #include #include #include diff --git a/services/Api.cpp b/services/Api.cpp index 652dd85..1b06814 100644 --- a/services/Api.cpp +++ b/services/Api.cpp @@ -5,6 +5,7 @@ #include "Api.h" #include "Settings.h" #include +#include template struct Callback { @@ -30,37 +31,41 @@ const std::string Api::_baseUrl = "https://vps.aliencat.pro:8443/"; SoupSession* Api::_session = soup_session_new(); template -boost::future Api::post(const std::string &method, const nlohmann::json& params) { +folly::Future Api::post(const std::string &method, const nlohmann::json& params) { std::string url = _baseUrl + method; auto msg = soup_message_new(SOUP_METHOD_POST, url.c_str()); - auto promise = std::make_shared>(); + auto promise = std::make_shared>(); auto callback = voidify([&, promise](SoupSession* session, SoupMessage* message) { if(message->status_code >= 200 && message->status_code < 300) { auto responseString = std::string(message->response_body->data, message->response_body->length); auto json = nlohmann::json::parse(responseString); if(json["success"].get()) { - std::cout << "response: " << responseString << std::endl; + //std::cout << "response: " << responseString << std::endl; auto user = json["data"].get(); - promise->set_value(user); + promise->setValue(user); } else { auto error = json["error"].get(); - promise->set_exception(FutureException(error)); + promise->setException(std::runtime_error(error)); } } else { - promise->set_exception(FutureException(message->reason_phrase)); + promise->setException(std::runtime_error(message->reason_phrase)); } }); auto jsonStr = params.dump(); - soup_message_set_request(msg, "application/json", SOUP_MEMORY_COPY, jsonStr.c_str(), jsonStr.size()); + soup_message_set_request(msg, "application/json", + SOUP_MEMORY_COPY, + jsonStr.c_str(), + jsonStr.size()); + soup_session_queue_message(_session, msg, callback.function, callback.state); - return promise->get_future(); + return promise->getFuture(); } -boost::future Api::login(std::string email, std::string password) { +fc::Task Api::login(std::string email, std::string password) { nlohmann::json params = { { "email", email }, diff --git a/services/Api.h b/services/Api.h index 4e0befd..fc68d13 100644 --- a/services/Api.h +++ b/services/Api.h @@ -8,9 +8,13 @@ #include #include #include +#include +#include #include "../models/User.h" -#include "../coro/Task.h" +#include "../coro/Coro.h" + +namespace fc = folly::coro; class Api { private: @@ -19,10 +23,10 @@ private: private: template - static boost::future post(const std::string& method, const nlohmann::json& params); + static folly::Future post(const std::string& method, const nlohmann::json& params); public: - static boost::future login(std::string email, std::string password); + static fc::Task login(std::string email, std::string password); };