From fe4199dace73ee38262528f7ae88cbfba99120dd Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 31 Dec 2018 12:01:59 +0100 Subject: Make thread-safe --- include/Window.hpp | 7 +++ run.sh | 2 + src/Window.cpp | 135 +++++++++++++++++++++++++++++++++++++++-------------- test.sh | 26 +++++++++++ 4 files changed, 134 insertions(+), 36 deletions(-) create mode 100755 test.sh diff --git a/include/Window.hpp b/include/Window.hpp index 4355fb8..645b578 100644 --- a/include/Window.hpp +++ b/include/Window.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace dchat { @@ -22,7 +23,9 @@ namespace dchat std::shared_ptr rooms; WindowNotification *windowNotification; private: + using DispatcherHandler = std::function; bool drawBackground(const Cairo::RefPtr &cairo); + void dispatchFunction(DispatcherHandler func); private: class OverlayDrawable : public Gtk::Overlay { @@ -53,5 +56,9 @@ namespace dchat std::vector backgroundNodes; int prevTimeMillis; sigc::connection drawBackgroundConnection; + + Glib::Dispatcher dispatcher; + std::mutex dispatcherMutex; + std::vector dispatcherHandlers; }; } \ No newline at end of file diff --git a/run.sh b/run.sh index 3fca183..c66d369 100755 --- a/run.sh +++ b/run.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e + script_path=`readlink -f $0` script_dir=`dirname $script_path` cd "$script_dir" diff --git a/src/Window.cpp b/src/Window.cpp index 5e4930f..255986a 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -68,7 +68,10 @@ namespace dchat { if(!rooms || !rooms->database) { - windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); + dispatchFunction([this]() + { + windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); + }); return; } @@ -76,17 +79,23 @@ namespace dchat { fprintf(stderr, "Trying to login with username %s\n", username.raw().c_str()); rooms->loginUser(username.raw(), password.raw()); - //windowNotification->show(Glib::ustring("Successfully logged in as ") + username); - drawBackgroundConnection.disconnect(); - chatWindow.show(); - stack.set_visible_child(chatWindow); - chatWindow.scrollToBottom(); + dispatchFunction([this]() + { + //windowNotification->show(Glib::ustring("Successfully logged in as ") + username); + drawBackgroundConnection.disconnect(); + chatWindow.show(); + stack.set_visible_child(chatWindow); + chatWindow.scrollToBottom(); + }); } catch(std::exception &e) { Glib::ustring errMsg = "Failed to login, reason: "; errMsg += e.what(); - windowNotification->show(errMsg); + dispatchFunction([this, errMsg]() + { + windowNotification->show(errMsg); + }); } }); @@ -94,7 +103,10 @@ namespace dchat { if(!rooms || !rooms->database) { - windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); + dispatchFunction([this]() + { + windowNotification->show("You are not connected to the bootstrap node yet! please wait..."); + }); return; } @@ -102,10 +114,13 @@ namespace dchat { fprintf(stderr, "Trying to register username %s\n", username.raw().c_str()); rooms->registerUser(username.raw(), password.raw()); - windowNotification->show(Glib::ustring("Successfully registered user ") + username); - drawBackgroundConnection.disconnect(); - chatWindow.show(); - stack.set_visible_child(chatWindow); + dispatchFunction([this]() + { + //windowNotification->show(Glib::ustring("Successfully registered user ") + username); + drawBackgroundConnection.disconnect(); + chatWindow.show(); + stack.set_visible_child(chatWindow); + }); } catch(std::exception &e) { @@ -113,13 +128,19 @@ namespace dchat errMsg += username.raw(); errMsg += ", reason: "; errMsg += e.what(); - windowNotification->show(errMsg); + dispatchFunction([this, errMsg]() + { + windowNotification->show(errMsg); + }); } }); loginWindow.setRegisterPasswordMismatch([this] { - windowNotification->show("Passwords do not match"); + dispatchFunction([this]() + { + windowNotification->show("Passwords do not match"); + }); }); auto bootstrapNodes = getBootstrapNodesFromFile(); @@ -136,52 +157,87 @@ namespace dchat roomCallbackFuncs.connectCallbackFunc = [this, bootstrapNode](std::shared_ptr rooms, const char *errMsg) { this->rooms = rooms; - if(rooms) + std::string errMsgStr = errMsg ? errMsg : "unknown"; + dispatchFunction([this, bootstrapNode, errMsgStr]() { - loginWindow.show(); - stack.set_visible_child(loginWindow); - std::string msg = "Connected to "; - msg += *bootstrapNode; - msg += ":27130"; - windowNotification->show(msg); - loginWindow.loginUsernameInput.grab_focus(); - } - else - { - std::string errMsgToShow = "Failed to connect to boostrap node, reason: "; - errMsgToShow += errMsg; - windowNotification->show(errMsgToShow); - } + if(this->rooms) + { + loginWindow.show(); + stack.set_visible_child(loginWindow); + std::string msg = "Connected to "; + msg += *bootstrapNode; + msg += ":27130"; + windowNotification->show(msg); + loginWindow.loginUsernameInput.grab_focus(); + } + else + { + std::string errMsgToShow = "Failed to connect to boostrap node, reason: "; + errMsgToShow += errMsgStr; + windowNotification->show(errMsgToShow); + } + }); }; roomCallbackFuncs.createRoomCallbackFunc = [this](std::shared_ptr room) { - chatWindow.addRoom(room); + dispatchFunction([this, room]() + { + chatWindow.addRoom(room); + }); }; roomCallbackFuncs.addUserCallbackFunc = [this](const RoomAddUserRequest &request) { - chatWindow.addUser(request); + dispatchFunction([this, request]() + { + chatWindow.addUser(request); + }); }; roomCallbackFuncs.addMessageCallbackFunc = [this](const RoomAddMessageRequest &request) { - chatWindow.addMessage(request); + dispatchFunction([this, request]() + { + chatWindow.addMessage(request); + }); }; roomCallbackFuncs.userChangeNicknameCallbackFunc = [this](const UserChangeNicknameRequest &request) { - chatWindow.setUserNickname(request); + dispatchFunction([this, request]() + { + chatWindow.setUserNickname(request); + }); }; roomCallbackFuncs.userChangeAvatarCallbackFunc = [this](const UserChangeAvatarRequest &request) { - chatWindow.setUserAvatar(request); + dispatchFunction([this, request]() + { + chatWindow.setUserAvatar(request); + }); }; roomCallbackFuncs.changeRoomNameCallbackFunc = [this](const RoomChangeNameRequest &request) { - chatWindow.changeRoomName(request); + dispatchFunction([this, request]() + { + chatWindow.changeRoomName(request); + }); }; roomCallbackFuncs.receiveInviteUserCallbackFunc = [this](const InviteUserRequest &request) { - chatWindow.addInviteRequest(request); + dispatchFunction([this, request]() + { + chatWindow.addInviteRequest(request); + }); }; + dispatcher.connect([this]() + { + std::lock_guard lock(dispatcherMutex); + for(DispatcherHandler &dispatcherHandler : dispatcherHandlers) + { + dispatcherHandler(); + } + dispatcherHandlers.clear(); + }); + Rooms::connect(bootstrapNode->c_str(), 27130, roomCallbackFuncs); backgroundRng.seed(std::random_device()()); @@ -222,6 +278,13 @@ namespace dchat } + void Window::dispatchFunction(DispatcherHandler func) + { + std::lock_guard lock(dispatcherMutex); + dispatcherHandlers.push_back(func); + dispatcher.emit(); + } + static void drawNode(const Cairo::RefPtr &cairo, double x, double y, double radius) { cairo->arc(x, y, radius, 0.0, 2.0 * M_PI); diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..ad72ae2 --- /dev/null +++ b/test.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +if [ "$#" -ne 1 ]; then + echo "Expected 1 argument, a home path" + exit 1 +fi + +script_path=`readlink -f $0` +script_dir=`dirname $script_path` +cd "$script_dir" + +HOME="$1" +if [ ! -f ~/.local/share/fonts/Lato-Regular.ttf ]; then + mkdir -p ~/.local/share/fonts + cp ./fonts/Lato-Regular.ttf ~/.local/share/fonts/Lato-Regular.ttf + fc-cache +fi +if [ ! -f ~/.local/share/fonts/Lato-Bold.ttf ]; then + mkdir -p ~/.local/share/fonts + cp ./fonts/Lato-Bold.ttf ~/.local/share/fonts/Lato-Bold.ttf + fc-cache +fi +platform=`sibs platform` +env GTK_THEME=Adwaita:light gdb ./sibs-build/$platform/debug/dchat \ No newline at end of file -- cgit v1.2.3