summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-10-30 14:00:44 +0100
committerMaxime Coste <frrrwww@gmail.com>2012-10-30 14:00:44 +0100
commit1ea4b3998a1a43b570e7891c253e0e426bee6a1c (patch)
tree26afe56676c03833fc1ffcdba9f4dab763a56fd5 /src
parentbc7dfec44cd588142915eabbbd740759ed299398 (diff)
Add a ClientManager for managing client lifetimes
Diffstat (limited to 'src')
-rw-r--r--src/client_manager.cc24
-rw-r--r--src/client_manager.hh42
-rw-r--r--src/commands.cc6
-rw-r--r--src/main.cc54
-rw-r--r--src/remote.cc2
-rw-r--r--src/remote.hh5
6 files changed, 100 insertions, 33 deletions
diff --git a/src/client_manager.cc b/src/client_manager.cc
new file mode 100644
index 00000000..6f30277d
--- /dev/null
+++ b/src/client_manager.cc
@@ -0,0 +1,24 @@
+#include "client_manager.hh"
+
+namespace Kakoune
+{
+
+void ClientManager::add_client(Client&& client)
+{
+ m_clients.emplace_back(std::move(client));
+}
+
+void ClientManager::remove_client_by_context(Context& context)
+{
+ for (auto it = m_clients.begin(); it != m_clients.end(); ++it)
+ {
+ if (it->context.get() == &context)
+ {
+ m_clients.erase(it);
+ return;
+ }
+ }
+ assert(false);
+}
+
+}
diff --git a/src/client_manager.hh b/src/client_manager.hh
new file mode 100644
index 00000000..a9dac1a0
--- /dev/null
+++ b/src/client_manager.hh
@@ -0,0 +1,42 @@
+#ifndef client_manager_hh_INCLUDED
+#define client_manager_hh_INCLUDED
+
+#include "context.hh"
+#include "input_handler.hh"
+
+namespace Kakoune
+{
+
+struct Client
+{
+ std::unique_ptr<UserInterface> ui;
+ std::unique_ptr<InputHandler> input_handler;
+ std::unique_ptr<Context> context;
+
+ Client(UserInterface* ui, Window& window)
+ : ui(ui),
+ input_handler(new InputHandler{}),
+ context(new Context(*input_handler, window, *ui)) {}
+
+ Client(Client&&) = default;
+ Client& operator=(Client&&) = default;
+};
+
+struct client_removed{};
+
+class ClientManager : public Singleton<ClientManager>
+{
+public:
+ void add_client(Client&& client);
+ void remove_client_by_context(Context& context);
+
+ bool empty() const { return m_clients.empty(); }
+ size_t count() const { return m_clients.size(); }
+private:
+ std::vector<Client> m_clients;
+};
+
+}
+
+#endif // client_manager_hh_INCLUDED
+
diff --git a/src/commands.cc b/src/commands.cc
index 392fa500..f6b3f767 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -16,6 +16,7 @@
#include "shell_manager.hh"
#include "event_manager.hh"
#include "color_registry.hh"
+#include "client_manager.hh"
#include <sys/types.h>
#include <sys/stat.h>
@@ -334,7 +335,7 @@ void quit(const CommandParameters& params, Context& context)
if (params.size() != 0)
throw wrong_argument_count();
- if (not force)
+ if (not force and ClientManager::instance().count() == 1)
{
std::vector<String> names;
for (auto& buffer : BufferManager::instance())
@@ -355,7 +356,8 @@ void quit(const CommandParameters& params, Context& context)
throw runtime_error(message);
}
}
- quit_requested = true;
+ ClientManager::instance().remove_client_by_context(context);
+ throw client_removed{};
}
template<bool force>
diff --git a/src/main.cc b/src/main.cc
index b20a917c..eb2ceedb 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -21,6 +21,7 @@
#include "file.hh"
#include "color_registry.hh"
#include "remote.hh"
+#include "client_manager.hh"
#if defined(__APPLE__)
#include <mach-o/dyld.h>
@@ -38,8 +39,6 @@ using namespace std::placeholders;
namespace Kakoune
{
-bool quit_requested = false;
-
template<InsertMode mode>
void do_insert(Context& context)
{
@@ -494,21 +493,7 @@ void register_registers()
}
}
-struct Client
-{
- std::unique_ptr<UserInterface> ui;
- std::unique_ptr<InputHandler> input_handler;
- std::unique_ptr<Context> context;
-
- Client(UserInterface* ui, Window& window)
- : ui(ui),
- input_handler(new InputHandler{}),
- context(new Context(*input_handler, window, *ui)) {}
-
- Client() {}
-};
-
-Client create_local_client(const String& file)
+void create_local_client(const String& file)
{
Buffer* buffer = nullptr;
UserInterface* ui = new NCursesUI{};
@@ -537,14 +522,16 @@ Client create_local_client(const String& file)
{
ui->print_status(error.description(), -1);
}
+ catch (Kakoune::client_removed&)
+ {
+ EventManager::instance().unwatch(0);
+ }
});
context->draw_ifn();
- return client;
+ ClientManager::instance().add_client(std::move(client));
}
-std::vector<Client> clients;
-
struct Server
{
Server()
@@ -583,8 +570,13 @@ struct Server
{
ui->print_status(error.description(), -1);
}
+ catch (Kakoune::client_removed&)
+ {
+ EventManager::instance().unwatch(sock);
+ close(sock);
+ }
});
- clients.push_back(std::move(client));
+ ClientManager::instance().add_client(std::move(client));
};
EventManager::instance().watch(m_listen_sock, accepter);
}
@@ -647,9 +639,16 @@ int main(int argc, char* argv[])
if (argc == 3 and String("-c") == argv[1])
{
- std::unique_ptr<RemoteClient> client(connect_to(argv[2]));
- while(not quit_requested)
- event_manager.handle_next_events();
+ try
+ {
+ std::unique_ptr<RemoteClient> client(connect_to(argv[2]));
+ while (true)
+ event_manager.handle_next_events();
+ }
+ catch (peer_disconnected&)
+ {
+ puts("disconnected");
+ }
return 0;
}
@@ -662,6 +661,7 @@ int main(int argc, char* argv[])
HighlighterRegistry highlighter_registry;
FilterRegistry filter_registry;
ColorRegistry color_registry;
+ ClientManager client_manager;
run_unit_tests();
@@ -677,7 +677,6 @@ int main(int argc, char* argv[])
Server server;
- Client local_client;
try
{
Context initialisation_context;
@@ -688,9 +687,10 @@ int main(int argc, char* argv[])
{
write_debug("error while parsing kakrc: " + error.description());
}
- local_client = create_local_client(argc > 1 ? argv[1] : "");
- while(not quit_requested)
+ create_local_client(argc > 1 ? argv[1] : "");
+
+ while (not client_manager.empty())
event_manager.handle_next_events();
}
catch (Kakoune::exception& error)
diff --git a/src/remote.cc b/src/remote.cc
index 7a715274..b3a0b6fd 100644
--- a/src/remote.cc
+++ b/src/remote.cc
@@ -108,6 +108,8 @@ template<>
String read<String>(int socket)
{
ByteCount length = read<ByteCount>(socket);
+ if (length == 0)
+ return String{};
char buffer[2048];
assert(length < 2048);
read(socket, buffer, (int)length);
diff --git a/src/remote.hh b/src/remote.hh
index aa14eeb3..976a5bf8 100644
--- a/src/remote.hh
+++ b/src/remote.hh
@@ -7,10 +7,7 @@
namespace Kakoune
{
-struct peer_disconnected : public runtime_error
-{
- peer_disconnected() : runtime_error("peer disconnected") {}
-};
+struct peer_disconnected {};
class RemoteUI : public UserInterface
{