mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-29 11:01:57 +00:00
more wip ipc refactor
This commit is contained in:
parent
94383d589b
commit
b3a544e880
173
command_line.cc
173
command_line.cc
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "compilation_database_loader.h"
|
#include "compilation_database_loader.h"
|
||||||
#include "indexer.h"
|
#include "indexer.h"
|
||||||
|
#include "ipc.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
|
|
||||||
bool ParsePreferredSymbolLocation(const std::string& content, PreferredSymbolLocation* obj) {
|
bool ParsePreferredSymbolLocation(const std::string& content, PreferredSymbolLocation* obj) {
|
||||||
@ -94,7 +95,13 @@ indexer.exe --index-file /work2/chrome/src/chrome/foo.cc
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ipc.h"
|
|
||||||
|
struct IpcMessage_IsAlive : public IpcMessage<IpcMessage_IsAlive> {
|
||||||
|
static IpcMessageId id;
|
||||||
|
};
|
||||||
|
|
||||||
|
IpcMessageId IpcMessage_IsAlive::id = "IsAlive";
|
||||||
|
|
||||||
|
|
||||||
void IndexerServerMain() {
|
void IndexerServerMain() {
|
||||||
IpcServer ipc("language_server");
|
IpcServer ipc("language_server");
|
||||||
@ -104,15 +111,13 @@ void IndexerServerMain() {
|
|||||||
|
|
||||||
std::cout << "Server has " << messages.size() << " messages" << std::endl;
|
std::cout << "Server has " << messages.size() << " messages" << std::endl;
|
||||||
for (auto& message : messages) {
|
for (auto& message : messages) {
|
||||||
switch (message->kind) {
|
if (message->runtime_id == IpcMessage_IsAlive::id) {
|
||||||
case JsonMessage::Kind::IsAlive:
|
|
||||||
{
|
|
||||||
IpcMessage_IsAlive response;
|
IpcMessage_IsAlive response;
|
||||||
ipc.SendToClient(0, &response); // todo: make non-blocking
|
ipc.SendToClient(0, &response); // todo: make non-blocking
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
else {
|
||||||
std::cerr << "Unhandled IPC message with kind " << static_cast<int>(message->kind) << std::endl;
|
std::cerr << "Unhandled IPC message with kind " << message->runtime_id << " (hash " << message->hashed_runtime_id << ")" << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -123,6 +128,37 @@ void IndexerServerMain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitReferences(IpcClient& ipc) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate thread whose only job is to read from stdin and
|
||||||
|
// dispatch read commands to the actual indexer program. This
|
||||||
|
// cannot be done on the main thread because reading from std::cin
|
||||||
|
// blocks.
|
||||||
|
void LanguageServerStdinToServerDispatcher(IpcClient& ipc) {
|
||||||
|
while (true) {
|
||||||
|
std::string input;
|
||||||
|
std::cin >> input;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main loop for the language server. |ipc| is connected to
|
||||||
|
// a server.
|
||||||
|
void LanguageServerLoop(IpcClient& ipc) {
|
||||||
|
while (true) {
|
||||||
|
std::string input;
|
||||||
|
std::cin >> input;
|
||||||
|
|
||||||
|
std::cout << "got input " << input << std::endl << std::endl;
|
||||||
|
|
||||||
|
if (input == "references") {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LanguageServerMain() {
|
void LanguageServerMain() {
|
||||||
IpcClient ipc("language_server", 0);
|
IpcClient ipc("language_server", 0);
|
||||||
|
|
||||||
@ -139,7 +175,7 @@ void LanguageServerMain() {
|
|||||||
std::vector<std::unique_ptr<BaseIpcMessage>> messages = ipc.TakeMessages();
|
std::vector<std::unique_ptr<BaseIpcMessage>> messages = ipc.TakeMessages();
|
||||||
bool has_server = false;
|
bool has_server = false;
|
||||||
for (auto& message : messages) {
|
for (auto& message : messages) {
|
||||||
if (message->kind == JsonMessage::Kind::IsAlive) {
|
if (message->runtime_id == IpcMessage_IsAlive::id) {
|
||||||
has_server = true;
|
has_server = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -152,10 +188,131 @@ void LanguageServerMain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Found indexer server" << std::endl;
|
std::cout << "Found indexer server" << std::endl;
|
||||||
|
LanguageServerLoop(ipc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if false
|
||||||
|
|
||||||
|
struct IpcMessage_IsAlive : public BaseIpcMessage {
|
||||||
|
IpcMessage_IsAlive();
|
||||||
|
|
||||||
|
// BaseIpcMessage:
|
||||||
|
void Serialize(Writer& writer) override;
|
||||||
|
void Deserialize(Reader& reader) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IpcMessage_ImportIndex : public BaseIpcMessage {
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
IpcMessage_ImportIndex();
|
||||||
|
|
||||||
|
// BaseMessage:
|
||||||
|
void Serialize(Writer& writer) override;
|
||||||
|
void Deserialize(Reader& reader) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IpcMessage_CreateIndex : public BaseIpcMessage {
|
||||||
|
std::string path;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
|
||||||
|
IpcMessage_CreateIndex();
|
||||||
|
|
||||||
|
// BaseMessage:
|
||||||
|
void Serialize(Writer& writer) override;
|
||||||
|
void Deserialize(Reader& reader) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
IpcMessage_IsAlive::IpcMessage_IsAlive() {
|
||||||
|
kind = JsonMessage::Kind::IsAlive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcMessage_IsAlive::Serialize(Writer& writer) {}
|
||||||
|
|
||||||
|
void IpcMessage_IsAlive::Deserialize(Reader& reader) {}
|
||||||
|
|
||||||
|
IpcMessage_ImportIndex::IpcMessage_ImportIndex() {
|
||||||
|
kind = JsonMessage::Kind::ImportIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcMessage_ImportIndex::Serialize(Writer& writer) {
|
||||||
|
writer.StartObject();
|
||||||
|
::Serialize(writer, "path", path);
|
||||||
|
writer.EndObject();
|
||||||
|
}
|
||||||
|
void IpcMessage_ImportIndex::Deserialize(Reader& reader) {
|
||||||
|
::Deserialize(reader, "path", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
IpcMessage_CreateIndex::IpcMessage_CreateIndex() {
|
||||||
|
kind = JsonMessage::Kind::CreateIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IpcMessage_CreateIndex::Serialize(Writer& writer) {
|
||||||
|
writer.StartObject();
|
||||||
|
::Serialize(writer, "path", path);
|
||||||
|
::Serialize(writer, "args", args);
|
||||||
|
writer.EndObject();
|
||||||
|
}
|
||||||
|
void IpcMessage_CreateIndex::Deserialize(Reader& reader) {
|
||||||
|
::Deserialize(reader, "path", path);
|
||||||
|
::Deserialize(reader, "args", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make it so we don't need an explicit list
|
||||||
|
// of available ipc message types. Maybe use string or
|
||||||
|
// a hash, not sure.
|
||||||
|
|
||||||
|
struct IpcMessage_DocumentSymbolsRequest : public BaseIpcMessage {
|
||||||
|
std::string document;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IpcMessage_DocumentSymbolsResponse : public BaseIpcMessage {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ListSymbols : public BaseType<ListSymbols> {
|
||||||
|
static IpcRegistry::Id id;
|
||||||
|
};
|
||||||
|
|
||||||
|
IpcRegistry::Id ListSymbols::id = "ListSymbols";
|
||||||
|
|
||||||
|
struct ListSymbol2s : public BaseType<ListSymbol2s> {
|
||||||
|
static IpcRegistry::Id id;
|
||||||
|
};
|
||||||
|
|
||||||
|
IpcRegistry::Id ListSymbol2s::id = "ListSymbols";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void main2() {
|
||||||
|
//ListSymbols l;
|
||||||
|
//auto& x = ListSymbols::register_;
|
||||||
|
//ListSymbol2s l2;
|
||||||
|
//auto& y = ListSymbol2s::register_;
|
||||||
|
|
||||||
|
std::cout << "main2" << std::endl;
|
||||||
|
std::cin.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if (argc == 1)
|
IpcMessage_IsAlive _;
|
||||||
|
|
||||||
|
//main2();
|
||||||
|
//return 0;
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
LanguageServerMain();
|
LanguageServerMain();
|
||||||
else
|
else
|
||||||
IndexerServerMain();
|
IndexerServerMain();
|
||||||
|
56
ipc.cc
56
ipc.cc
@ -24,40 +24,19 @@ void JsonMessage::SetPayload(size_t payload_size, const char* payload) {
|
|||||||
memcpy(payload_dest, payload, payload_size);
|
memcpy(payload_dest, payload, payload_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcMessage_IsAlive::IpcMessage_IsAlive() {
|
BaseIpcMessage::BaseIpcMessage(BaseIpcMessage::DoNotDeriveDirectly) {}
|
||||||
kind = JsonMessage::Kind::IsAlive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IpcMessage_IsAlive::Serialize(Writer& writer) {}
|
BaseIpcMessage::~BaseIpcMessage() {}
|
||||||
|
|
||||||
void IpcMessage_IsAlive::Deserialize(Reader& reader) {}
|
void BaseIpcMessage::Serialize(Writer& writer) {}
|
||||||
|
|
||||||
IpcMessage_ImportIndex::IpcMessage_ImportIndex() {
|
void BaseIpcMessage::Deserialize(Reader& reader) {}
|
||||||
kind = JsonMessage::Kind::ImportIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IpcMessage_ImportIndex::Serialize(Writer& writer) {
|
|
||||||
writer.StartObject();
|
|
||||||
::Serialize(writer, "path", path);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
void IpcMessage_ImportIndex::Deserialize(Reader& reader) {
|
|
||||||
::Deserialize(reader, "path", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcMessage_CreateIndex::IpcMessage_CreateIndex() {
|
IpcRegistry IpcRegistry::Instance;
|
||||||
kind = JsonMessage::Kind::CreateIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IpcMessage_CreateIndex::Serialize(Writer& writer) {
|
std::unique_ptr<BaseIpcMessage> IpcRegistry::Allocate(int id) {
|
||||||
writer.StartObject();
|
return std::unique_ptr<BaseIpcMessage>((*allocators)[id]());
|
||||||
::Serialize(writer, "path", path);
|
|
||||||
::Serialize(writer, "args", args);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
void IpcMessage_CreateIndex::Deserialize(Reader& reader) {
|
|
||||||
::Deserialize(reader, "path", path);
|
|
||||||
::Deserialize(reader, "args", args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcDirectionalChannel::IpcDirectionalChannel(const std::string& name) {
|
IpcDirectionalChannel::IpcDirectionalChannel(const std::string& name) {
|
||||||
@ -100,12 +79,12 @@ void IpcDirectionalChannel::PushMessage(BaseIpcMessage* message) {
|
|||||||
if ((*shared->shared_bytes_used + sizeof(JsonMessage) + payload_size) >= shmem_size)
|
if ((*shared->shared_bytes_used + sizeof(JsonMessage) + payload_size) >= shmem_size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
get_free_message()->kind = message->kind;
|
get_free_message()->message_id = message->hashed_runtime_id;
|
||||||
get_free_message()->SetPayload(payload_size, output.GetString());
|
get_free_message()->SetPayload(payload_size, output.GetString());
|
||||||
|
|
||||||
*shared->shared_bytes_used += sizeof(JsonMessage) + get_free_message()->payload_size;
|
*shared->shared_bytes_used += sizeof(JsonMessage) + get_free_message()->payload_size;
|
||||||
assert(*shared->shared_bytes_used < shmem_size);
|
assert(*shared->shared_bytes_used < shmem_size);
|
||||||
get_free_message()->kind = JsonMessage::Kind::Invalid;
|
get_free_message()->message_id = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,27 +101,14 @@ std::vector<std::unique_ptr<BaseIpcMessage>> IpcDirectionalChannel::TakeMessages
|
|||||||
|
|
||||||
memcpy(local_block, shared->shared_start, *shared->shared_bytes_used);
|
memcpy(local_block, shared->shared_start, *shared->shared_bytes_used);
|
||||||
*shared->shared_bytes_used = 0;
|
*shared->shared_bytes_used = 0;
|
||||||
get_free_message()->kind = JsonMessage::Kind::Invalid;
|
get_free_message()->message_id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<BaseIpcMessage>> result;
|
std::vector<std::unique_ptr<BaseIpcMessage>> result;
|
||||||
|
|
||||||
char* message = local_block;
|
char* message = local_block;
|
||||||
while (remaining_bytes > 0) {
|
while (remaining_bytes > 0) {
|
||||||
std::unique_ptr<BaseIpcMessage> base_message;
|
std::unique_ptr<BaseIpcMessage> base_message = IpcRegistry::Instance.Allocate(as_message(message)->message_id);
|
||||||
switch (as_message(message)->kind) {
|
|
||||||
case JsonMessage::Kind::IsAlive:
|
|
||||||
base_message = std::make_unique<IpcMessage_IsAlive>();
|
|
||||||
break;
|
|
||||||
case JsonMessage::Kind::CreateIndex:
|
|
||||||
base_message = std::make_unique<IpcMessage_CreateIndex>();
|
|
||||||
break;
|
|
||||||
case JsonMessage::Kind::ImportIndex:
|
|
||||||
base_message = std::make_unique<IpcMessage_ImportIndex>();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
rapidjson::Document document;
|
rapidjson::Document document;
|
||||||
document.Parse(as_message(message)->payload(), as_message(message)->payload_size);
|
document.Parse(as_message(message)->payload(), as_message(message)->payload_size);
|
||||||
|
105
ipc.h
105
ipc.h
@ -4,6 +4,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/prettywriter.h>
|
#include <rapidjson/prettywriter.h>
|
||||||
@ -21,56 +22,98 @@ using Reader = rapidjson::Document;
|
|||||||
// completely different address.
|
// completely different address.
|
||||||
|
|
||||||
struct JsonMessage {
|
struct JsonMessage {
|
||||||
enum class Kind {
|
int message_id;
|
||||||
Invalid,
|
|
||||||
IsAlive,
|
|
||||||
CreateIndex,
|
|
||||||
ImportIndex,
|
|
||||||
};
|
|
||||||
|
|
||||||
Kind kind;
|
|
||||||
size_t payload_size;
|
size_t payload_size;
|
||||||
|
|
||||||
const char* payload();
|
const char* payload();
|
||||||
void SetPayload(size_t payload_size, const char* payload);
|
void SetPayload(size_t payload_size, const char* payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using IpcMessageId = std::string;
|
||||||
|
|
||||||
struct BaseIpcMessage {
|
struct BaseIpcMessage {
|
||||||
JsonMessage::Kind kind;
|
virtual ~BaseIpcMessage();
|
||||||
virtual ~BaseIpcMessage() {}
|
|
||||||
|
|
||||||
virtual void Serialize(Writer& writer) = 0;
|
virtual void Serialize(Writer& writer);
|
||||||
virtual void Deserialize(Reader& reader) = 0;
|
virtual void Deserialize(Reader& reader);
|
||||||
|
|
||||||
|
IpcMessageId runtime_id;
|
||||||
|
int hashed_runtime_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
private:
|
||||||
|
template<typename T>
|
||||||
|
friend struct IpcMessage;
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum class DoNotDeriveDirectly {
|
||||||
|
DeriveFromIpcMessageInstead
|
||||||
|
};
|
||||||
|
BaseIpcMessage(DoNotDeriveDirectly);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IpcMessage_IsAlive : public BaseIpcMessage {
|
struct IpcRegistry {
|
||||||
IpcMessage_IsAlive();
|
using Allocator = std::function<BaseIpcMessage*()>;
|
||||||
|
|
||||||
// BaseIpcMessage:
|
// Use unique_ptrs so we can initialize on first use
|
||||||
void Serialize(Writer& writer) override;
|
// (static init order might not be right).
|
||||||
void Deserialize(Reader& reader) override;
|
std::unique_ptr<std::unordered_map<int, Allocator>> allocators;
|
||||||
|
std::unique_ptr<std::unordered_map<int, std::string>> hash_to_id;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int RegisterAllocator();
|
||||||
|
|
||||||
|
std::unique_ptr<BaseIpcMessage> Allocate(int id);
|
||||||
|
|
||||||
|
static IpcRegistry* instance() {
|
||||||
|
// TODO: Remove static magic. Just call register explicitly.
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
static IpcRegistry* instance_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IpcMessage_ImportIndex : public BaseIpcMessage {
|
template<typename T>
|
||||||
std::string path;
|
int IpcRegistry::RegisterAllocator() {
|
||||||
|
if (!allocators) {
|
||||||
|
allocators = std::make_unique<std::unordered_map<int, Allocator>>();
|
||||||
|
hash_to_id = std::make_unique<std::unordered_map<int, std::string>>();
|
||||||
|
}
|
||||||
|
|
||||||
IpcMessage_ImportIndex();
|
IpcMessageId id = T::id;
|
||||||
|
|
||||||
// BaseMessage:
|
int hash = std::hash<IpcMessageId>()(id);
|
||||||
void Serialize(Writer& writer) override;
|
auto it = allocators->find(hash);
|
||||||
void Deserialize(Reader& reader) override;
|
assert(allocators->find(hash) == allocators->end() && "There is already an IPC message with the given id");
|
||||||
|
|
||||||
|
(*hash_to_id)[hash] = id;
|
||||||
|
(*allocators)[hash] = []() {
|
||||||
|
return new T();
|
||||||
|
};
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TChild>
|
||||||
|
struct IpcMessage : public BaseIpcMessage {
|
||||||
|
IpcMessage();
|
||||||
|
|
||||||
|
static int hashed_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IpcMessage_CreateIndex : public BaseIpcMessage {
|
template<typename TChild>
|
||||||
std::string path;
|
int IpcMessage<TChild>::hashed_id_ = IpcRegistry::Instance.RegisterAllocator<TChild>();
|
||||||
std::vector<std::string> args;
|
|
||||||
|
template<typename TChild>
|
||||||
|
IpcMessage<TChild>::IpcMessage()
|
||||||
|
: BaseIpcMessage(DoNotDeriveDirectly::DeriveFromIpcMessageInstead) {
|
||||||
|
runtime_id = TChild::id;
|
||||||
|
hashed_runtime_id = hashed_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IpcMessage_CreateIndex();
|
|
||||||
|
|
||||||
// BaseMessage:
|
|
||||||
void Serialize(Writer& writer) override;
|
|
||||||
void Deserialize(Reader& reader) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IpcDirectionalChannel {
|
struct IpcDirectionalChannel {
|
||||||
// NOTE: We keep all pointers in terms of char* so pointer arithmetic is
|
// NOTE: We keep all pointers in terms of char* so pointer arithmetic is
|
||||||
|
Loading…
Reference in New Issue
Block a user