Add a ClientManager for managing client lifetimes

This commit is contained in:
Maxime Coste 2012-10-30 14:00:44 +01:00
parent bc7dfec44c
commit 1ea4b3998a
6 changed files with 100 additions and 33 deletions

24
src/client_manager.cc Normal file
View 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
View 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

View File

@ -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>

View File

@ -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)

View File

@ -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);

View File

@ -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
{