Add a ClientManager for managing client lifetimes
This commit is contained in:
parent
bc7dfec44c
commit
1ea4b3998a
24
src/client_manager.cc
Normal file
24
src/client_manager.cc
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
src/client_manager.hh
Normal file
42
src/client_manager.hh
Normal file
|
@ -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
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "shell_manager.hh"
|
#include "shell_manager.hh"
|
||||||
#include "event_manager.hh"
|
#include "event_manager.hh"
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
|
#include "client_manager.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -334,7 +335,7 @@ void quit(const CommandParameters& params, Context& context)
|
||||||
if (params.size() != 0)
|
if (params.size() != 0)
|
||||||
throw wrong_argument_count();
|
throw wrong_argument_count();
|
||||||
|
|
||||||
if (not force)
|
if (not force and ClientManager::instance().count() == 1)
|
||||||
{
|
{
|
||||||
std::vector<String> names;
|
std::vector<String> names;
|
||||||
for (auto& buffer : BufferManager::instance())
|
for (auto& buffer : BufferManager::instance())
|
||||||
|
@ -355,7 +356,8 @@ void quit(const CommandParameters& params, Context& context)
|
||||||
throw runtime_error(message);
|
throw runtime_error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quit_requested = true;
|
ClientManager::instance().remove_client_by_context(context);
|
||||||
|
throw client_removed{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool force>
|
template<bool force>
|
||||||
|
|
50
src/main.cc
50
src/main.cc
|
@ -21,6 +21,7 @@
|
||||||
#include "file.hh"
|
#include "file.hh"
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
#include "remote.hh"
|
#include "remote.hh"
|
||||||
|
#include "client_manager.hh"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
|
@ -38,8 +39,6 @@ using namespace std::placeholders;
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
bool quit_requested = false;
|
|
||||||
|
|
||||||
template<InsertMode mode>
|
template<InsertMode mode>
|
||||||
void do_insert(Context& context)
|
void do_insert(Context& context)
|
||||||
{
|
{
|
||||||
|
@ -494,21 +493,7 @@ void register_registers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Client
|
void create_local_client(const String& file)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
Buffer* buffer = nullptr;
|
Buffer* buffer = nullptr;
|
||||||
UserInterface* ui = new NCursesUI{};
|
UserInterface* ui = new NCursesUI{};
|
||||||
|
@ -537,14 +522,16 @@ Client create_local_client(const String& file)
|
||||||
{
|
{
|
||||||
ui->print_status(error.description(), -1);
|
ui->print_status(error.description(), -1);
|
||||||
}
|
}
|
||||||
|
catch (Kakoune::client_removed&)
|
||||||
|
{
|
||||||
|
EventManager::instance().unwatch(0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
context->draw_ifn();
|
context->draw_ifn();
|
||||||
return client;
|
ClientManager::instance().add_client(std::move(client));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Client> clients;
|
|
||||||
|
|
||||||
struct Server
|
struct Server
|
||||||
{
|
{
|
||||||
Server()
|
Server()
|
||||||
|
@ -583,8 +570,13 @@ struct Server
|
||||||
{
|
{
|
||||||
ui->print_status(error.description(), -1);
|
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);
|
EventManager::instance().watch(m_listen_sock, accepter);
|
||||||
}
|
}
|
||||||
|
@ -646,10 +638,17 @@ int main(int argc, char* argv[])
|
||||||
EventManager event_manager;
|
EventManager event_manager;
|
||||||
|
|
||||||
if (argc == 3 and String("-c") == argv[1])
|
if (argc == 3 and String("-c") == argv[1])
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
std::unique_ptr<RemoteClient> client(connect_to(argv[2]));
|
std::unique_ptr<RemoteClient> client(connect_to(argv[2]));
|
||||||
while(not quit_requested)
|
while (true)
|
||||||
event_manager.handle_next_events();
|
event_manager.handle_next_events();
|
||||||
|
}
|
||||||
|
catch (peer_disconnected&)
|
||||||
|
{
|
||||||
|
puts("disconnected");
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,6 +661,7 @@ int main(int argc, char* argv[])
|
||||||
HighlighterRegistry highlighter_registry;
|
HighlighterRegistry highlighter_registry;
|
||||||
FilterRegistry filter_registry;
|
FilterRegistry filter_registry;
|
||||||
ColorRegistry color_registry;
|
ColorRegistry color_registry;
|
||||||
|
ClientManager client_manager;
|
||||||
|
|
||||||
run_unit_tests();
|
run_unit_tests();
|
||||||
|
|
||||||
|
@ -677,7 +677,6 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
Server server;
|
Server server;
|
||||||
|
|
||||||
Client local_client;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Context initialisation_context;
|
Context initialisation_context;
|
||||||
|
@ -688,9 +687,10 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
write_debug("error while parsing kakrc: " + error.description());
|
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();
|
event_manager.handle_next_events();
|
||||||
}
|
}
|
||||||
catch (Kakoune::exception& error)
|
catch (Kakoune::exception& error)
|
||||||
|
|
|
@ -108,6 +108,8 @@ template<>
|
||||||
String read<String>(int socket)
|
String read<String>(int socket)
|
||||||
{
|
{
|
||||||
ByteCount length = read<ByteCount>(socket);
|
ByteCount length = read<ByteCount>(socket);
|
||||||
|
if (length == 0)
|
||||||
|
return String{};
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
assert(length < 2048);
|
assert(length < 2048);
|
||||||
read(socket, buffer, (int)length);
|
read(socket, buffer, (int)length);
|
||||||
|
|
|
@ -7,10 +7,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
struct peer_disconnected : public runtime_error
|
struct peer_disconnected {};
|
||||||
{
|
|
||||||
peer_disconnected() : runtime_error("peer disconnected") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class RemoteUI : public UserInterface
|
class RemoteUI : public UserInterface
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user