diff options
Diffstat (limited to 'graphics/asymptote/LspCpp/include/LibLsp/JsonRpc')
20 files changed, 1332 insertions, 1147 deletions
diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h index b89f32f166..496be29844 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h @@ -7,12 +7,12 @@ namespace Cancellation { struct Params { - /** - * The request id to cancel. - */ - lsRequestId id; - - MAKE_SWAP_METHOD(Cancellation::Params, id); + /** + * The request id to cancel. + */ + lsRequestId id; + + MAKE_SWAP_METHOD(Cancellation::Params, id); }; }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h index a5f550041d..6a8cf7a2a6 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h @@ -5,44 +5,44 @@ class Condition { public: - std::mutex m_mutex; - std::condition_variable m_condition; - ~Condition() { - m_condition.notify_all(); - } - void notify(std::unique_ptr<T> data) noexcept - { - { - std::lock_guard<std::mutex> eventLock(m_mutex); - any.swap(data); - } - // wake up one waiter - m_condition.notify_one(); - }; + std::mutex m_mutex; + std::condition_variable m_condition; + ~Condition() { + m_condition.notify_all(); + } + void notify(std::unique_ptr<T> data) noexcept + { + { + std::lock_guard<std::mutex> eventLock(m_mutex); + any.swap(data); + } + // wake up one waiter + m_condition.notify_one(); + }; - - std::unique_ptr<T> wait(unsigned timeout=0) - { - std::unique_lock<std::mutex> ul(m_mutex); - if (!timeout) { - m_condition.wait(ul,[&]() { - if (!any) - return false; - return true; - }); - } - else{ - if(!any){ - std::cv_status status = m_condition.wait_for(ul, std::chrono::milliseconds(timeout)); - if (status == std::cv_status::timeout) - { - return {}; - } - } - } - return std::unique_ptr<T>(any.release()); - - } + + std::unique_ptr<T> wait(unsigned timeout=0) + { + std::unique_lock<std::mutex> ul(m_mutex); + if (!timeout) { + m_condition.wait(ul,[&]() { + if (!any) + return false; + return true; + }); + } + else{ + if(!any){ + std::cv_status status = m_condition.wait_for(ul, std::chrono::milliseconds(timeout)); + if (status == std::cv_status::timeout) + { + return {}; + } + } + } + return std::unique_ptr<T>(any.release()); + + } private: - std::unique_ptr<T> any; + std::unique_ptr<T> any; }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h index 01d8e8ca91..d752711a3a 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h @@ -15,38 +15,38 @@ using GenericNotificationHandler = std::function< bool(std::unique_ptr<LspMessag class Endpoint { public: - virtual ~Endpoint() = default; - virtual bool onRequest(std::unique_ptr<LspMessage>) = 0; - virtual bool notify(std::unique_ptr<LspMessage>) = 0; - - virtual bool onResponse(const std::string&, std::unique_ptr<LspMessage>) = 0; - virtual void registerRequestHandler(const std::string&, GenericResponseHandler ) = 0; - virtual void registerNotifyHandler(const std::string&, GenericNotificationHandler ) = 0; + virtual ~Endpoint() = default; + virtual bool onRequest(std::unique_ptr<LspMessage>) = 0; + virtual bool notify(std::unique_ptr<LspMessage>) = 0; + + virtual bool onResponse(const std::string&, std::unique_ptr<LspMessage>) = 0; + virtual void registerRequestHandler(const std::string&, GenericResponseHandler ) = 0; + virtual void registerNotifyHandler(const std::string&, GenericNotificationHandler ) = 0; }; class GenericEndpoint :public Endpoint { public: - GenericEndpoint(lsp::Log& l):log(l){} - bool notify(std::unique_ptr<LspMessage>) override; - bool onResponse(const std::string&, std::unique_ptr<LspMessage>) override; - - bool onRequest(std::unique_ptr<LspMessage>) override; - std::map< std::string, GenericRequestHandler > method2request; - std::map< std::string, GenericResponseHandler > method2response; - std::map< std::string, GenericNotificationHandler > method2notification; - - void registerRequestHandler(const std::string& method, GenericResponseHandler cb) override - { - method2request[method] = cb; - } - - void registerNotifyHandler(const std::string& method, GenericNotificationHandler cb) override - { - method2notification[method] = cb; - } - lsp::Log& log; + GenericEndpoint(lsp::Log& l):log(l){} + bool notify(std::unique_ptr<LspMessage>) override; + bool onResponse(const std::string&, std::unique_ptr<LspMessage>) override; + + bool onRequest(std::unique_ptr<LspMessage>) override; + std::map< std::string, GenericRequestHandler > method2request; + std::map< std::string, GenericResponseHandler > method2response; + std::map< std::string, GenericNotificationHandler > method2notification; + + void registerRequestHandler(const std::string& method, GenericResponseHandler cb) override + { + method2request[method] = cb; + } + + void registerNotifyHandler(const std::string& method, GenericNotificationHandler cb) override + { + method2notification[method] = cb; + } + lsp::Log& log; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h index bda6e65d46..6c29ee8f0e 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h @@ -4,179 +4,179 @@ #include <vector> namespace lsp { - class Log - { - public: - virtual ~Log() = default; - - enum class Level - { - /** - * OFF is a special level that can be used to turn off logging. - - */ - OFF = 1, - - /** - * SEVERE is a message level indicating a serious failure. - * <p> - * In general SEVERE messages should describe events that are - * of considerable importance and which will prevent normal - * program execution. They should be reasonably intelligible - * to end users and to system administrators. - - */ - SEVERE = 2, - - /** - * WARNING is a message level indicating a potential problem. - * <p> - * In general WARNING messages should describe events that will - * be of interest to end users or system managers, or which - * indicate potential problems. - - * - */ - WARNING = 3, - /** - * INFO is a message level for informational messages. - * <p> - * Typically INFO messages will be written to the console - * or its equivalent. So the INFO level should only be - * used for reasonably significant messages that will - * make sense to end users and system administrators. - - */ - INFO = 3, - /** - * CONFIG is a message level for static configuration messages. - * <p> - * CONFIG messages are intended to provide a variety of static - * configuration information, to assist in debugging problems - * that may be associated with particular configurations. - * For example, CONFIG message might include the CPU type, - * the graphics depth, the GUI look-and-feel, etc. - * This level is initialized to <CODE>4</CODE>. - */ - - CONFIG = 4, - - - - /** - * FINE is a message level providing tracing information. - * <p> - * All of FINE, FINER, and FINEST are intended for relatively - * detailed tracing. The exact meaning of the three levels will - * vary between subsystems, but in general, FINEST should be used - * for the most voluminous detailed output, FINER for somewhat - * less detailed output, and FINE for the lowest volume (and - * most important) messages. - * <p> - * In general the FINE level should be used for information - * that will be broadly interesting to developers who do not have - * a specialized interest in the specific subsystem. - * <p> - * FINE messages might include things like minor (recoverable) - * failures. Issues indicating potential performance problems - * are also worth logging as FINE. - * This level is initialized to <CODE>5</CODE>. - */ - FINE = 5, - - /** - * FINER indicates a fairly detailed tracing message. - * By default logging calls for entering, returning, or throwing - * an exception are traced at this level. - * This level is initialized to <CODE>400</CODE>. - */ - FINER = 6, - - /** - * FINEST indicates a highly detailed tracing message. - * This level is initialized to <CODE>300</CODE>. - */ - FINEST = 7, - - /** - * ALL indicates that all messages should be logged. - * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>. - */ - ALL, - }; - virtual void log(Level level, std::wstring&& msg) = 0; - virtual void log(Level level, const std::wstring& msg) = 0; - virtual void log(Level level, std::string&& msg) = 0; - virtual void log(Level level, const std::string& msg) = 0; - - void info(const std::string& msg) - { - log(Level::INFO, msg); - } - void info(const std::wstring& msg) - { - log(Level::INFO, msg); - } - void error(const std::string& msg) - { - log(Level::SEVERE, msg); - } - void error(const std::wstring& msg) - { - log(Level::SEVERE, msg); - } - void warning(const std::string& msg) - { - log(Level::WARNING, msg); - } - void warning(const std::wstring& msg) - { - log(Level::WARNING, msg); - } - }; + class Log + { + public: + virtual ~Log() = default; + + enum class Level + { + /** + * OFF is a special level that can be used to turn off logging. + + */ + OFF = 1, + + /** + * SEVERE is a message level indicating a serious failure. + * <p> + * In general SEVERE messages should describe events that are + * of considerable importance and which will prevent normal + * program execution. They should be reasonably intelligible + * to end users and to system administrators. + + */ + SEVERE = 2, + + /** + * WARNING is a message level indicating a potential problem. + * <p> + * In general WARNING messages should describe events that will + * be of interest to end users or system managers, or which + * indicate potential problems. + + * + */ + WARNING = 3, + /** + * INFO is a message level for informational messages. + * <p> + * Typically INFO messages will be written to the console + * or its equivalent. So the INFO level should only be + * used for reasonably significant messages that will + * make sense to end users and system administrators. + + */ + INFO = 3, + /** + * CONFIG is a message level for static configuration messages. + * <p> + * CONFIG messages are intended to provide a variety of static + * configuration information, to assist in debugging problems + * that may be associated with particular configurations. + * For example, CONFIG message might include the CPU type, + * the graphics depth, the GUI look-and-feel, etc. + * This level is initialized to <CODE>4</CODE>. + */ + + CONFIG = 4, + + + + /** + * FINE is a message level providing tracing information. + * <p> + * All of FINE, FINER, and FINEST are intended for relatively + * detailed tracing. The exact meaning of the three levels will + * vary between subsystems, but in general, FINEST should be used + * for the most voluminous detailed output, FINER for somewhat + * less detailed output, and FINE for the lowest volume (and + * most important) messages. + * <p> + * In general the FINE level should be used for information + * that will be broadly interesting to developers who do not have + * a specialized interest in the specific subsystem. + * <p> + * FINE messages might include things like minor (recoverable) + * failures. Issues indicating potential performance problems + * are also worth logging as FINE. + * This level is initialized to <CODE>5</CODE>. + */ + FINE = 5, + + /** + * FINER indicates a fairly detailed tracing message. + * By default logging calls for entering, returning, or throwing + * an exception are traced at this level. + * This level is initialized to <CODE>400</CODE>. + */ + FINER = 6, + + /** + * FINEST indicates a highly detailed tracing message. + * This level is initialized to <CODE>300</CODE>. + */ + FINEST = 7, + + /** + * ALL indicates that all messages should be logged. + * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>. + */ + ALL, + }; + virtual void log(Level level, std::wstring&& msg) = 0; + virtual void log(Level level, const std::wstring& msg) = 0; + virtual void log(Level level, std::string&& msg) = 0; + virtual void log(Level level, const std::string& msg) = 0; + + void info(const std::string& msg) + { + log(Level::INFO, msg); + } + void info(const std::wstring& msg) + { + log(Level::INFO, msg); + } + void error(const std::string& msg) + { + log(Level::SEVERE, msg); + } + void error(const std::wstring& msg) + { + log(Level::SEVERE, msg); + } + void warning(const std::string& msg) + { + log(Level::WARNING, msg); + } + void warning(const std::wstring& msg) + { + log(Level::WARNING, msg); + } + }; } class MessageIssue { public: - std::string text; + std::string text; - lsp::Log::Level code; + lsp::Log::Level code; - MessageIssue(const std::string& text, lsp::Log::Level code) :text(text), code(code) - { + MessageIssue(const std::string& text, lsp::Log::Level code) :text(text), code(code) + { - } - MessageIssue(std::string&& text, lsp::Log::Level code) :text(text), code(code) - { + } + MessageIssue(std::string&& text, lsp::Log::Level code) :text(text), code(code) + { - } + } - std::string getText() { - return text; - } + std::string getText() { + return text; + } - lsp::Log::Level getIssueCode() { - return code; - } + lsp::Log::Level getIssueCode() { + return code; + } - std::string toString() { - return getText(); - } + std::string toString() { + return getText(); + } }; class MessageIssueHandler { public: - /** - * Handle issues found while parsing or validating a message. The list of issues must not be empty. - */ - virtual ~MessageIssueHandler() = default; - - virtual void handle(std::vector<MessageIssue>&&) = 0; - virtual void handle( MessageIssue&&) = 0; + /** + * Handle issues found while parsing or validating a message. The list of issues must not be empty. + */ + virtual ~MessageIssueHandler() = default; + + virtual void handle(std::vector<MessageIssue>&&) = 0; + virtual void handle( MessageIssue&&) = 0; }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h index 7e238b0cf6..f019fbf121 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h @@ -13,49 +13,49 @@ using GenericNotificationJsonHandler = std::function< std::unique_ptr<LspMessag class MessageJsonHandler { public: - std::map< std::string, GenericRequestJsonHandler > method2request; - std::map< std::string, GenericResponseJsonHandler > method2response; - std::map< std::string, GenericNotificationJsonHandler > method2notification; - - - const GenericRequestJsonHandler* GetRequestJsonHandler(const char* methodInfo) const - { - const auto findIt = method2request.find(methodInfo); - return findIt == method2request.end() ? nullptr : &findIt->second; - } - - void SetRequestJsonHandler(const std::string& methodInfo, GenericRequestJsonHandler handler) - { - method2request[methodInfo] = handler; - } - - const GenericResponseJsonHandler* GetResponseJsonHandler(const char* methodInfo) const - { - const auto findIt = method2response.find(methodInfo); - return findIt == method2response.end() ? nullptr : &findIt->second; - } - - void SetResponseJsonHandler(const std::string& methodInfo,GenericResponseJsonHandler handler) - { - method2response[methodInfo] = handler; - } - - const GenericNotificationJsonHandler* GetNotificationJsonHandler(const char* methodInfo) const - { - const auto findIt = method2notification.find(methodInfo); - return findIt == method2notification.end() ? nullptr : &findIt->second; - } - - void SetNotificationJsonHandler(const std::string& methodInfo, GenericNotificationJsonHandler handler) - { - method2notification[methodInfo] = handler; - } - - - - std::unique_ptr<LspMessage> parseResponseMessage(const std::string&, Reader&); - std::unique_ptr<LspMessage> parseRequstMessage(const std::string&, Reader&); - bool resovleResponseMessage(Reader&, std::pair<std::string, std::unique_ptr<LspMessage>>& result); - std::unique_ptr<LspMessage> parseNotificationMessage(const std::string&, Reader&); + std::map< std::string, GenericRequestJsonHandler > method2request; + std::map< std::string, GenericResponseJsonHandler > method2response; + std::map< std::string, GenericNotificationJsonHandler > method2notification; + + + const GenericRequestJsonHandler* GetRequestJsonHandler(const char* methodInfo) const + { + const auto findIt = method2request.find(methodInfo); + return findIt == method2request.end() ? nullptr : &findIt->second; + } + + void SetRequestJsonHandler(const std::string& methodInfo, GenericRequestJsonHandler handler) + { + method2request[methodInfo] = handler; + } + + const GenericResponseJsonHandler* GetResponseJsonHandler(const char* methodInfo) const + { + const auto findIt = method2response.find(methodInfo); + return findIt == method2response.end() ? nullptr : &findIt->second; + } + + void SetResponseJsonHandler(const std::string& methodInfo,GenericResponseJsonHandler handler) + { + method2response[methodInfo] = handler; + } + + const GenericNotificationJsonHandler* GetNotificationJsonHandler(const char* methodInfo) const + { + const auto findIt = method2notification.find(methodInfo); + return findIt == method2notification.end() ? nullptr : &findIt->second; + } + + void SetNotificationJsonHandler(const std::string& methodInfo, GenericNotificationJsonHandler handler) + { + method2notification[methodInfo] = handler; + } + + + + std::unique_ptr<LspMessage> parseResponseMessage(const std::string&, Reader&); + std::unique_ptr<LspMessage> parseRequstMessage(const std::string&, Reader&); + bool resovleResponseMessage(Reader&, std::pair<std::string, std::unique_ptr<LspMessage>>& result); + std::unique_ptr<LspMessage> parseNotificationMessage(const std::string&, Reader&); }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h index ab7a29a17f..2affe3b3ff 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h @@ -5,9 +5,9 @@ class MessageProducer { public: - - - typedef std::function< void(std::string&&) > MessageConsumer; - virtual ~MessageProducer() = default; - virtual void listen(MessageConsumer) = 0; + + + typedef std::function< void(std::string&&) > MessageConsumer; + virtual ~MessageProducer() = default; + virtual void listen(MessageConsumer) = 0; }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h index e4841b5703..cdee9e572e 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h @@ -9,54 +9,54 @@ // NotificationInMessage does not have |id|. struct NotificationInMessage : public LspMessage { - Kind GetKid() override - { - return NOTIFICATION_MESSAGE; - } - MethodType GetMethodType() const override - { - return method.c_str(); - } - void SetMethodType(MethodType _t) override - { - method = _t; - } - std::string method; + Kind GetKid() override + { + return NOTIFICATION_MESSAGE; + } + MethodType GetMethodType() const override + { + return method.c_str(); + } + void SetMethodType(MethodType _t) override + { + method = _t; + } + std::string method; }; template <class T, class TDerived > struct lsNotificationInMessage : NotificationInMessage { - void ReflectWriter(Writer& writer) override { - Reflect(writer, static_cast<TDerived&>(*this)); - } - lsNotificationInMessage(MethodType _method) - { - method = _method; - } - - static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { - - TDerived* temp = new TDerived(); - - std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); - // Reflect may throw and *message will be partially deserialized. - Reflect(visitor, static_cast<TDerived&>(*temp)); - return message; - - } - void swap(lsNotificationInMessage& arg) noexcept - { - method.swap(method); - std::swap(params, arg.params); - } - T params; + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + lsNotificationInMessage(MethodType _method) + { + method = _method; + } + + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + + TDerived* temp = new TDerived(); + + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + + } + void swap(lsNotificationInMessage& arg) noexcept + { + method.swap(method); + std::swap(params, arg.params); + } + T params; }; #define DEFINE_NOTIFICATION_TYPE(MSG,paramType,methodInfo)\ namespace MSG {\ - struct notify : public lsNotificationInMessage< paramType , notify >{\ - static constexpr MethodType kMethodInfo = methodInfo;\ - notify():lsNotificationInMessage(kMethodInfo){} \ - };\ + struct notify : public lsNotificationInMessage< paramType , notify >{\ + static constexpr MethodType kMethodInfo = methodInfo;\ + notify():lsNotificationInMessage(kMethodInfo){} \ + };\ };\ MAKE_REFLECT_STRUCT(MSG::notify, jsonrpc,method, params) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h index 3ae6b567a5..4045098f1b 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h @@ -12,6 +12,7 @@ #include "MessageIssue.h" #include "LibLsp/JsonRpc/MessageJsonHandler.h" #include "Endpoint.h" +#include "future.h" class MessageJsonHandler; @@ -19,74 +20,74 @@ class Endpoint; struct LspMessage; class RemoteEndPoint; namespace lsp { - class ostream; - class istream; - - //////////////////////////////////////////////////////////////////////////////// - // ResponseOrError<T> - //////////////////////////////////////////////////////////////////////////////// - - // ResponseOrError holds either the response to a request or an error - // message. - template <typename T> - struct ResponseOrError { - using Request = T; - ResponseOrError(); - ResponseOrError(const T& response); - ResponseOrError(T&& response); - ResponseOrError(const Rsp_Error& error); - ResponseOrError(Rsp_Error&& error); - ResponseOrError(const ResponseOrError& other); - ResponseOrError(ResponseOrError&& other) noexcept; - - ResponseOrError& operator=(const ResponseOrError& other); - ResponseOrError& operator=(ResponseOrError&& other) noexcept; - bool IsError() const { return is_error; } - std::string ToJson() - { - if (is_error) return error.ToJson(); - return response.ToJson(); - } - T response; - Rsp_Error error; // empty represents success. - bool is_error; - }; - - template <typename T> - ResponseOrError<T>::ResponseOrError(): is_error(false) - { - } - - template <typename T> - ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp), is_error(false) {} - template <typename T> - ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)), is_error(false) {} - template <typename T> - ResponseOrError<T>::ResponseOrError(const Rsp_Error& err) : error(err), is_error(true) {} - template <typename T> - ResponseOrError<T>::ResponseOrError(Rsp_Error&& err) : error(std::move(err)), is_error(true) {} - template <typename T> - ResponseOrError<T>::ResponseOrError(const ResponseOrError& other) - : response(other.response), error(other.error), is_error(other.is_error) {} - template <typename T> - ResponseOrError<T>::ResponseOrError(ResponseOrError&& other) noexcept - : response(std::move(other.response)), error(std::move(other.error)), is_error(other.is_error) {} - template <typename T> - ResponseOrError<T>& ResponseOrError<T>::operator=( - const ResponseOrError& other) { - response = other.response; - error = other.error; - is_error = other.is_error; - return *this; - } - template <typename T> - ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) noexcept - { - response = std::move(other.response); - error = std::move(other.error); - is_error = other.is_error; - return *this; - } + class ostream; + class istream; + + //////////////////////////////////////////////////////////////////////////////// + // ResponseOrError<T> + //////////////////////////////////////////////////////////////////////////////// + + // ResponseOrError holds either the response to a request or an error + // message. + template <typename T> + struct ResponseOrError { + using Request = T; + ResponseOrError(); + ResponseOrError(const T& response); + ResponseOrError(T&& response); + ResponseOrError(const Rsp_Error& error); + ResponseOrError(Rsp_Error&& error); + ResponseOrError(const ResponseOrError& other); + ResponseOrError(ResponseOrError&& other) noexcept; + + ResponseOrError& operator=(const ResponseOrError& other); + ResponseOrError& operator=(ResponseOrError&& other) noexcept; + bool IsError() const { return is_error; } + std::string ToJson() + { + if (is_error) return error.ToJson(); + return response.ToJson(); + } + T response; + Rsp_Error error; // empty represents success. + bool is_error; + }; + + template <typename T> + ResponseOrError<T>::ResponseOrError(): is_error(false) + { + } + + template <typename T> + ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp), is_error(false) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)), is_error(false) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(const Rsp_Error& err) : error(err), is_error(true) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(Rsp_Error&& err) : error(std::move(err)), is_error(true) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(const ResponseOrError& other) + : response(other.response), error(other.error), is_error(other.is_error) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(ResponseOrError&& other) noexcept + : response(std::move(other.response)), error(std::move(other.error)), is_error(other.is_error) {} + template <typename T> + ResponseOrError<T>& ResponseOrError<T>::operator=( + const ResponseOrError& other) { + response = other.response; + error = other.error; + is_error = other.is_error; + return *this; + } + template <typename T> + ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) noexcept + { + response = std::move(other.response); + error = std::move(other.error); + is_error = other.is_error; + return *this; + } } @@ -94,247 +95,253 @@ namespace lsp { class RemoteEndPoint :MessageIssueHandler { - template <typename F, int N> - using ParamType = lsp::traits::ParameterType<F, N>; + template <typename F, int N> + using ParamType = lsp::traits::ParameterType<F, N>; - template <typename T> - using IsRequest = lsp::traits::EnableIfIsType<RequestInMessage, T>; + template <typename T> + using IsRequest = lsp::traits::EnableIfIsType<RequestInMessage, T>; - template <typename T> - using IsResponse = lsp::traits::EnableIfIsType<ResponseInMessage, T>; + template <typename T> + using IsResponse = lsp::traits::EnableIfIsType<ResponseInMessage, T>; - template <typename T> - using IsNotify = lsp::traits::EnableIfIsType<NotificationInMessage, T>; + template <typename T> + using IsNotify = lsp::traits::EnableIfIsType<NotificationInMessage, T>; - template <typename F, typename ReturnType> - using IsRequestHandler = lsp::traits::EnableIf<lsp::traits::CompatibleWith< - F, - std::function<ReturnType(const RequestInMessage&)>>:: - value>; + template <typename F, typename ReturnType> + using IsRequestHandler = lsp::traits::EnableIf<lsp::traits::CompatibleWith< + F, + std::function<ReturnType(const RequestInMessage&)>>:: + value>; - template <typename F, typename ReturnType> - using IsRequestHandlerWithMonitor = lsp::traits::EnableIf<lsp::traits::CompatibleWith< - F, - std::function<ReturnType(const RequestInMessage&,const CancelMonitor&)>>:: - value>; + template <typename F, typename ReturnType> + using IsRequestHandlerWithMonitor = lsp::traits::EnableIf<lsp::traits::CompatibleWith< + F, + std::function<ReturnType(const RequestInMessage&,const CancelMonitor&)>>:: + value>; public: - - RemoteEndPoint(const std::shared_ptr <MessageJsonHandler>& json_handler, - const std::shared_ptr < Endpoint >& localEndPoint, - lsp::Log& _log, uint8_t max_workers = 2); - - ~RemoteEndPoint() override; - template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> - IsRequestHandler< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) - { - ProcessRequestJsonHandler(handler); - local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { - auto req = reinterpret_cast<const RequestType*>(msg.get()); - lsp::ResponseOrError<ResponseType> res(handler(*req)); - if (res.is_error) { - res.error.id = req->id; - send(res.error); - } - else - { - res.response.id = req->id; - send(res.response); - } - return true; - }); - } - template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> - IsRequestHandlerWithMonitor< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) { - ProcessRequestJsonHandler(handler); - local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { - auto req = static_cast<const RequestType*>(msg.get()); - lsp::ResponseOrError<ResponseType> res(handler(*req , getCancelMonitor(req->id))); - if (res.is_error) { - res.error.id = req->id; - send(res.error); - } - else - { - res.response.id = req->id; - send(res.response); - } - return true; - }); - } - using RequestErrorCallback = std::function<void(const Rsp_Error&)>; - - template <typename T, typename F, typename ResponseType = ParamType<F, 0> > - void send(T& request, F&& handler, RequestErrorCallback onError) - { - ProcessRequestJsonHandler(handler); - auto cb = [=](std::unique_ptr<LspMessage> msg) { - if (!msg) - return true; - const auto result = msg.get(); - - if (static_cast<ResponseInMessage*>(result)->IsErrorType()) { - const auto rsp_error = static_cast<const Rsp_Error*>(result); - onError(*rsp_error); - } - else { - handler(*static_cast<ResponseType*>(result)); - } - - return true; - }; - internalSendRequest(request, cb); - } - - - template <typename F, typename NotifyType = ParamType<F, 0> > - IsNotify<NotifyType> registerHandler(F&& handler) { - { - std::lock_guard<std::mutex> lock(m_sendMutex); - if (!jsonHandler->GetNotificationJsonHandler(NotifyType::kMethodInfo)) - { - jsonHandler->SetNotificationJsonHandler(NotifyType::kMethodInfo, - [](Reader& visitor) - { - return NotifyType::ReflectReader(visitor); - }); - } - } - local_endpoint->registerNotifyHandler(NotifyType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { - handler(*static_cast<NotifyType*>(msg.get())); - return true; - }); - } - - template <typename T, typename = IsRequest<T>> - std::future< lsp::ResponseOrError<typename T::Response> > send(T& request) { - - ProcessResponseJsonHandler(request); - using Response = typename T::Response; - auto promise = std::make_shared< std::promise<lsp::ResponseOrError<Response>>>(); - auto cb = [=](std::unique_ptr<LspMessage> msg) { - if (!msg) - return true; - auto result = msg.get(); - - if (reinterpret_cast<ResponseInMessage*>(result)->IsErrorType()) - { - Rsp_Error* rsp_error = static_cast<Rsp_Error*>(result); - Rsp_Error temp; - std::swap(temp, *rsp_error); - promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); - } - else - { - Response temp; - std::swap(temp, *static_cast<Response*>(result)); - promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); - } - return true; - }; - internalSendRequest(request, cb); - return promise->get_future(); - } - - template <typename T, typename = IsRequest<T>> - std::unique_ptr<lsp::ResponseOrError<typename T::Response>> waitResponse(T& request, const unsigned time_out = 0) - { - auto future_rsp = send(request); - if (time_out == 0) - { - future_rsp.wait(); - } - else - { - auto state = future_rsp.wait_for(std::chrono::milliseconds(time_out)); - if (std::future_status::timeout == state) - { - return {}; - } - } - - using Response = typename T::Response; - return std::make_unique<lsp::ResponseOrError<Response>>(std::move(future_rsp.get())); - } - - void send(NotificationInMessage& msg) - { - sendMsg(msg); - } - - void send(ResponseInMessage& msg) - { - sendMsg(msg); - } - - void sendNotification(NotificationInMessage& msg) - { - send(msg); - } - void sendResponse(ResponseInMessage& msg) - { - send(msg); - } - void startProcessingMessages(std::shared_ptr<lsp::istream> r, - std::shared_ptr<lsp::ostream> w); - - bool IsWorking() const - { - if (message_producer_thread_) - return true; - return false; - } - void Stop(); - - std::unique_ptr<LspMessage> internalWaitResponse(RequestInMessage&, unsigned time_out = 0); - - void internalSendRequest(RequestInMessage&, GenericResponseHandler); - - void handle(std::vector<MessageIssue>&&) override; - void handle(MessageIssue&&) override; + + RemoteEndPoint(const std::shared_ptr <MessageJsonHandler>& json_handler, + const std::shared_ptr < Endpoint >& localEndPoint, + lsp::Log& _log, uint8_t max_workers = 2); + + ~RemoteEndPoint() override; + template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> + IsRequestHandler< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) + { + processRequestJsonHandler(handler); + local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + auto req = reinterpret_cast<const RequestType*>(msg.get()); + lsp::ResponseOrError<ResponseType> res(handler(*req)); + if (res.is_error) { + res.error.id = req->id; + send(res.error); + } + else + { + res.response.id = req->id; + send(res.response); + } + return true; + }); + } + template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> + IsRequestHandlerWithMonitor< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) { + processRequestJsonHandler(handler); + local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + auto req = static_cast<const RequestType*>(msg.get()); + lsp::ResponseOrError<ResponseType> res(handler(*req , getCancelMonitor(req->id))); + if (res.is_error) { + res.error.id = req->id; + send(res.error); + } + else + { + res.response.id = req->id; + send(res.response); + } + return true; + }); + } + using RequestErrorCallback = std::function<void(const Rsp_Error&)>; + + template <typename T, typename F, typename ResponseType = ParamType<F, 0> > + void send(T& request, F&& handler, RequestErrorCallback onError) + { + processRequestJsonHandler(handler); + auto cb = [=](std::unique_ptr<LspMessage> msg) { + if (!msg) + return true; + const auto result = msg.get(); + + if (static_cast<ResponseInMessage*>(result)->IsErrorType()) { + const auto rsp_error = static_cast<const Rsp_Error*>(result); + onError(*rsp_error); + } + else { + handler(*static_cast<ResponseType*>(result)); + } + + return true; + }; + internalSendRequest(request, cb); + } + + + template <typename F, typename NotifyType = ParamType<F, 0> > + IsNotify<NotifyType> registerHandler(F&& handler) { + { + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetNotificationJsonHandler(NotifyType::kMethodInfo)) + { + jsonHandler->SetNotificationJsonHandler(NotifyType::kMethodInfo, + [](Reader& visitor) + { + return NotifyType::ReflectReader(visitor); + }); + } + } + local_endpoint->registerNotifyHandler(NotifyType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + handler(*static_cast<NotifyType*>(msg.get())); + return true; + }); + } + + template <typename T, typename = IsRequest<T>> + lsp::future< lsp::ResponseOrError<typename T::Response> > send(T& request) { + + processResponseJsonHandler(request); + using Response = typename T::Response; + auto promise = std::make_shared< lsp::promise<lsp::ResponseOrError<Response>>>(); + auto cb = [=](std::unique_ptr<LspMessage> msg) { + if (!msg) + return true; + auto result = msg.get(); + + if (reinterpret_cast<ResponseInMessage*>(result)->IsErrorType()) + { + Rsp_Error* rsp_error = static_cast<Rsp_Error*>(result); + Rsp_Error temp; + std::swap(temp, *rsp_error); + promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); + } + else + { + Response temp; + std::swap(temp, *static_cast<Response*>(result)); + promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); + } + return true; + }; + internalSendRequest(request, cb); + return promise->get_future(); + } + + template <typename T, typename = IsRequest<T>> + std::unique_ptr<lsp::ResponseOrError<typename T::Response>> waitResponse(T& request, const unsigned time_out = 0) + { + auto future_rsp = send(request); + if (time_out == 0) + { + future_rsp.wait(); + } + else + { + auto state = future_rsp.wait_for(std::chrono::milliseconds(time_out)); + if (lsp::future_status::timeout == state) + { + return {}; + } + } + + using Response = typename T::Response; + return std::make_unique<lsp::ResponseOrError<Response>>(std::move(future_rsp.get())); + } + + void send(NotificationInMessage& msg) + { + sendMsg(msg); + } + + void send(ResponseInMessage& msg) + { + sendMsg(msg); + } + + void sendNotification(NotificationInMessage& msg) + { + send(msg); + } + void sendResponse(ResponseInMessage& msg) + { + send(msg); + } + template <typename T> + T createRequest() { + auto req = T(); + req.id.set(getNextRequestId()); + return req; + } + + int getNextRequestId(); + + bool cancelRequest(const lsRequestId&); + + void startProcessingMessages(std::shared_ptr<lsp::istream> r, + std::shared_ptr<lsp::ostream> w); + + bool isWorking() const; + void stop(); + + std::unique_ptr<LspMessage> internalWaitResponse(RequestInMessage&, unsigned time_out = 0); + + bool internalSendRequest(RequestInMessage &info, GenericResponseHandler handler); + + void handle(std::vector<MessageIssue>&&) override; + void handle(MessageIssue&&) override; private: - CancelMonitor getCancelMonitor(const lsRequestId&); - void sendMsg(LspMessage& msg); - void mainLoop(std::unique_ptr<LspMessage>); - bool dispatch(const std::string&); - template <typename F, typename RequestType = ParamType<F, 0>> - IsRequest<RequestType> ProcessRequestJsonHandler(const F& handler) { - std::lock_guard<std::mutex> lock(m_sendMutex); - if (!jsonHandler->GetRequestJsonHandler(RequestType::kMethodInfo)) - { - jsonHandler->SetRequestJsonHandler(RequestType::kMethodInfo, - [](Reader& visitor) - { - return RequestType::ReflectReader(visitor); - }); - } - } - template <typename T, typename = IsRequest<T>> - void ProcessResponseJsonHandler(T& request) - { - using Response = typename T::Response; - std::lock_guard<std::mutex> lock(m_sendMutex); - if (!jsonHandler->GetResponseJsonHandler(T::kMethodInfo)) - { - jsonHandler->SetResponseJsonHandler(T::kMethodInfo, [](Reader& visitor) - { - if (visitor.HasMember("error")) - return Rsp_Error::ReflectReader(visitor); - return Response::ReflectReader(visitor); - }); - } - } - - struct Data; - - Data* d_ptr; - - std::shared_ptr < MessageJsonHandler> jsonHandler; - std::mutex m_sendMutex; - - std::shared_ptr < Endpoint > local_endpoint; + CancelMonitor getCancelMonitor(const lsRequestId&); + void sendMsg(LspMessage& msg); + void mainLoop(std::unique_ptr<LspMessage>); + bool dispatch(const std::string&); + template <typename F, typename RequestType = ParamType<F, 0>> + IsRequest<RequestType> processRequestJsonHandler(const F& handler) { + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetRequestJsonHandler(RequestType::kMethodInfo)) + { + jsonHandler->SetRequestJsonHandler(RequestType::kMethodInfo, + [](Reader& visitor) + { + return RequestType::ReflectReader(visitor); + }); + } + } + template <typename T, typename = IsRequest<T>> + void processResponseJsonHandler(T& request) + { + using Response = typename T::Response; + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetResponseJsonHandler(T::kMethodInfo)) + { + jsonHandler->SetResponseJsonHandler(T::kMethodInfo, [](Reader& visitor) + { + if (visitor.HasMember("error")) + return Rsp_Error::ReflectReader(visitor); + return Response::ReflectReader(visitor); + }); + } + } + + struct Data; + + Data* d_ptr; + + std::shared_ptr < MessageJsonHandler> jsonHandler; + std::mutex m_sendMutex; + + std::shared_ptr < Endpoint > local_endpoint; public: - std::shared_ptr < std::thread > message_producer_thread_; + std::shared_ptr < std::thread > message_producer_thread_; }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h index 163d038a2e..0775b36dba 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h @@ -10,14 +10,14 @@ #include "lsResponseMessage.h" struct RequestInMessage : public LspMessage { - // number or string, actually no null - lsRequestId id; - std::string method; - Kind GetKid() override - { - return REQUEST_MESSAGE; - } - + // number or string, actually no null + lsRequestId id; + std::string method; + Kind GetKid() override + { + return REQUEST_MESSAGE; + } + }; @@ -25,45 +25,45 @@ struct RequestInMessage : public LspMessage { template <class T, class TDerived > struct lsRequest : public RequestInMessage { - lsRequest(MethodType _method) - { - method = _method; - } - MethodType GetMethodType() const override { return method.c_str(); } - void SetMethodType(MethodType _method) override - { - method = _method; - } \ - void ReflectWriter(Writer& writer) override { - Reflect(writer, static_cast<TDerived&>(*this)); - } - - static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + lsRequest(MethodType _method) + { + method = _method; + } + MethodType GetMethodType() const override { return method.c_str(); } + void SetMethodType(MethodType _method) override + { + method = _method; + } \ + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { - TDerived* temp = new TDerived(); - std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); - // Reflect may throw and *message will be partially deserialized. - Reflect(visitor, static_cast<TDerived&>(*temp)); - return message; - } - void swap(lsRequest& arg) noexcept - { - id.swap(arg.id); - method.swap(method); - std::swap(params, arg.params); - } - T params; + TDerived* temp = new TDerived(); + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + } + void swap(lsRequest& arg) noexcept + { + id.swap(arg.id); + method.swap(method); + std::swap(params, arg.params); + } + T params; }; #define DEFINE_REQUEST_RESPONSE_TYPE(MSG,request_param,response_result,methodInfo)\ namespace MSG {\ - struct response :public ResponseMessage< response_result, response> {}; \ - struct request : public lsRequest< request_param , request >{\ - static constexpr MethodType kMethodInfo = methodInfo;\ - request():lsRequest(kMethodInfo){} \ - using Response = response;\ - };\ + struct response :public ResponseMessage< response_result, response> {}; \ + struct request : public lsRequest< request_param , request >{\ + static constexpr MethodType kMethodInfo = methodInfo;\ + request():lsRequest(kMethodInfo){} \ + using Response = response;\ + };\ };\ MAKE_REFLECT_STRUCT(MSG::request, jsonrpc, id, method, params);\ MAKE_REFLECT_STRUCT(MSG::response, jsonrpc, id, result); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h index 439a9f1b0e..e039891f5f 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h @@ -7,42 +7,42 @@ #include "MessageIssue.h" namespace lsp { - class istream; + class istream; } class StreamMessageProducer : public MessageProducer { public: - struct Headers - { - int contentLength = -1; - std::string charset; - void clear() - { - contentLength = -1; - charset.clear(); - } - }; - bool handleMessage(Headers& headers, MessageConsumer callBack); - StreamMessageProducer( - MessageIssueHandler& message_issue_handler, std::shared_ptr < lsp::istream> _input) - : issueHandler(message_issue_handler), - input(_input) - { - } - StreamMessageProducer( - MessageIssueHandler& message_issue_handler) - : issueHandler(message_issue_handler) - { - } - - bool keepRunning = false; - void listen(MessageConsumer) override; - void bind(std::shared_ptr < lsp::istream>); - void parseHeader(std::string& line, Headers& headers); + struct Headers + { + int contentLength = -1; + std::string charset; + void clear() + { + contentLength = -1; + charset.clear(); + } + }; + bool handleMessage(Headers& headers, MessageConsumer callBack); + StreamMessageProducer( + MessageIssueHandler& message_issue_handler, std::shared_ptr < lsp::istream> _input) + : issueHandler(message_issue_handler), + input(_input) + { + } + StreamMessageProducer( + MessageIssueHandler& message_issue_handler) + : issueHandler(message_issue_handler) + { + } + + bool keepRunning = false; + void listen(MessageConsumer) override; + void bind(std::shared_ptr < lsp::istream>); + void parseHeader(std::string& line, Headers& headers); private: - MessageIssueHandler& issueHandler; - std::shared_ptr < lsp::istream> input; - + MessageIssueHandler& issueHandler; + std::shared_ptr < lsp::istream> input; + }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h index e533acf056..a377be8c3e 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h @@ -36,5 +36,5 @@ namespace lsp void do_stop(); Data* d_ptr = nullptr; }; -} // namespace +} // namespace diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/future.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/future.h new file mode 100644 index 0000000000..8e241d96e9 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/future.h @@ -0,0 +1,178 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <condition_variable> +#include <memory> +#include <mutex> + +namespace lsp { + +// internal functionality +namespace detail { +template <typename T> +struct promise_state { + T val; + std::mutex mutex; + std::condition_variable cv; + bool hasVal = false; +}; +} // namespace detail + +// forward declaration +template <typename T> +class promise; + +// future_status is the enumeration returned by future::wait_for and +// future::wait_until. +enum class future_status { + ready, + timeout, +}; + +// future is a minimal reimplementation of std::future, that does not suffer +// from TSAN false positives. See: +// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69204 +template <typename T> +class future { + public: + using State = detail::promise_state<T>; + + // constructors + inline future() = default; + inline future(future&&) = default; + + // valid() returns true if the future has an internal state. + bool valid() const; + + // get() blocks until the future has a valid result, and returns it. + // The future must have a valid internal state to call this method. + inline T get(); + + // wait() blocks until the future has a valid result. + // The future must have a valid internal state to call this method. + void wait() const; + + // wait_for() blocks until the future has a valid result, or the timeout is + // reached. + // The future must have a valid internal state to call this method. + template <class Rep, class Period> + future_status wait_for( + const std::chrono::duration<Rep, Period>& timeout) const; + + // wait_until() blocks until the future has a valid result, or the timeout is + // reached. + // The future must have a valid internal state to call this method. + template <class Clock, class Duration> + future_status wait_until( + const std::chrono::time_point<Clock, Duration>& timeout) const; + + private: + friend promise<T>; + future(const future&) = delete; + inline future(const std::shared_ptr<State>& state); + + std::shared_ptr<State> state = std::make_shared<State>(); +}; + +template <typename T> +future<T>::future(const std::shared_ptr<State>& s) : state(s) {} + +template <typename T> +bool future<T>::valid() const { + return static_cast<bool>(state); +} + +template <typename T> +T future<T>::get() { + std::unique_lock<std::mutex> lock(state->mutex); + state->cv.wait(lock, [&] { return state->hasVal; }); + return state->val; +} + +template <typename T> +void future<T>::wait() const { + std::unique_lock<std::mutex> lock(state->mutex); + state->cv.wait(lock, [&] { return state->hasVal; }); +} + +template <typename T> +template <class Rep, class Period> +future_status future<T>::wait_for( + const std::chrono::duration<Rep, Period>& timeout) const { + std::unique_lock<std::mutex> lock(state->mutex); + return state->cv.wait_for(lock, timeout, [&] { return state->hasVal; }) + ? future_status::ready + : future_status::timeout; +} + +template <typename T> +template <class Clock, class Duration> +future_status future<T>::wait_until( + const std::chrono::time_point<Clock, Duration>& timeout) const { + std::unique_lock<std::mutex> lock(state->mutex); + return state->cv.wait_until(lock, timeout, [&] { return state->hasVal; }) + ? future_status::ready + : future_status::timeout; +} + +// promise is a minimal reimplementation of std::promise, that does not suffer +// from TSAN false positives. See: +// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69204 +template <typename T> +class promise { + public: + // constructors + inline promise() = default; + inline promise(promise&& other) = default; + inline promise(const promise& other) = default; + + // set_value() stores value to the shared state. + // set_value() must only be called once. + inline void set_value(const T& value) const; + inline void set_value(T&& value) const; + + // get_future() returns a future sharing this promise's state. + future<T> get_future(); + + private: + using State = detail::promise_state<T>; + std::shared_ptr<State> state = std::make_shared<State>(); +}; + +template <typename T> +future<T> promise<T>::get_future() { + return future<T>(state); +} + +template <typename T> +void promise<T>::set_value(const T& value) const { + std::unique_lock<std::mutex> lock(state->mutex); + state->val = value; + state->hasVal = true; + state->cv.notify_all(); +} + +template <typename T> +void promise<T>::set_value(T&& value) const { + std::unique_lock<std::mutex> lock(state->mutex); + state->val = std::move(value); + state->hasVal = true; + state->cv.notify_all(); +} + +} // namespace lsp + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h index 98ee91b544..34e6232917 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h @@ -10,7 +10,7 @@ class JsonReader : public Reader { std::vector<const char*> path_; public: - rapidjson::GenericValue<rapidjson::UTF8<>>* m_; + rapidjson::GenericValue<rapidjson::UTF8<>>* m_; JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>>* m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } @@ -35,10 +35,10 @@ class JsonReader : public Reader { bool HasMember(const char* x) override { - if (m_->IsObject()) - return m_->HasMember(x); - else - return false; + if (m_->IsObject()) + return m_->HasMember(x); + else + return false; } std::unique_ptr<Reader> operator[](const char* x) override { auto& sub = (*m_)[x]; @@ -59,7 +59,7 @@ class JsonReader : public Reader { class JsonWriter : public Writer { public: - rapidjson::Writer<rapidjson::StringBuffer>* m_; + rapidjson::Writer<rapidjson::StringBuffer>* m_; JsonWriter(rapidjson::Writer<rapidjson::StringBuffer>* m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h index 87e94669ab..2efc80b19a 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h @@ -3,49 +3,49 @@ #include "LibLsp/JsonRpc/serializer.h" struct lsRequestId { - // The client can send the request id as an int or a string. We should output - // the same format we received. - enum Type { kNone, kInt, kString }; - Type type = kNone; + // The client can send the request id as an int or a string. We should output + // the same format we received. + enum Type { kNone, kInt, kString }; + Type type = kNone; - int value = -1; - std::string k_string; - bool has_value() const { return type != kNone; } - void swap(lsRequestId& arg) noexcept - { - std::swap(arg, *this); - } - void set(int v) - { - value = v; - type = kInt; - } - void set(const std::string& v) - { - k_string = v; - type = kString; - } - bool operator==(const lsRequestId& rhs) const - { - if (type != rhs.type) return false; - if (type == kInt) - return value == rhs.value; - return k_string == rhs.k_string; - } - bool operator!=(const lsRequestId& rhs) const - { - return !operator==(rhs); - } - bool operator<(const lsRequestId& rhs) const - { - if (type != rhs.type) return false; - if (type == kInt) - return value < rhs.value; - return k_string < rhs.k_string; - } + int value = -1; + std::string k_string; + bool has_value() const { return type != kNone; } + void swap(lsRequestId& arg) noexcept + { + std::swap(arg, *this); + } + void set(int v) + { + value = v; + type = kInt; + } + void set(const std::string& v) + { + k_string = v; + type = kString; + } + bool operator==(const lsRequestId& rhs) const + { + if (type != rhs.type) return false; + if (type == kInt) + return value == rhs.value; + return k_string == rhs.k_string; + } + bool operator!=(const lsRequestId& rhs) const + { + return !operator==(rhs); + } + bool operator<(const lsRequestId& rhs) const + { + if (type != rhs.type) return false; + if (type == kInt) + return value < rhs.value; + return k_string < rhs.k_string; + } }; void Reflect(Reader& visitor, lsRequestId& value); void Reflect(Writer& visitor, lsRequestId& value); // Debug method to convert an id to a string. -std::string ToString(const lsRequestId& id);
\ No newline at end of file +std::string ToString(const lsRequestId& id); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h index ba94167cf8..68ad502b0c 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h @@ -7,65 +7,65 @@ struct ResponseInMessage :public LspMessage { - lsRequestId id; - std::string m_methodType; + lsRequestId id; + std::string m_methodType; - virtual MethodType GetMethodType() const override - { - return m_methodType.data(); - }; - virtual void SetMethodType(MethodType _type) override - { - m_methodType = _type; - }; + virtual MethodType GetMethodType() const override + { + return m_methodType.data(); + }; + virtual void SetMethodType(MethodType _type) override + { + m_methodType = _type; + }; - Kind GetKid() override - { - return RESPONCE_MESSAGE; - } - virtual bool IsErrorType() - { - return false; - } + Kind GetKid() override + { + return RESPONCE_MESSAGE; + } + virtual bool IsErrorType() + { + return false; + } }; template <class TDerived > struct BaseResponseMessage : ResponseInMessage { - void ReflectWriter(Writer& writer) override { - Reflect(writer, static_cast<TDerived&>(*this)); - } - static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { - TDerived* temp = new TDerived(); - std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); - // Reflect may throw and *message will be partially deserialized. - Reflect(visitor, static_cast<TDerived&>(*temp)); - return message; - } + TDerived* temp = new TDerived(); + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + } }; template <class T, class TDerived > struct ResponseMessage : BaseResponseMessage<TDerived> { - T result; - void swap(ResponseMessage<T, TDerived>& arg) noexcept - { - std::swap(result, arg.result); - this->id.swap(arg.id); - this->m_methodType.swap(arg.m_methodType); - } + T result; + void swap(ResponseMessage<T, TDerived>& arg) noexcept + { + std::swap(result, arg.result); + this->id.swap(arg.id); + this->m_methodType.swap(arg.m_methodType); + } }; template <class T, class TDerived > struct ResponseError : BaseResponseMessage<TDerived> { - T error; - bool IsErrorType() override { return true; } - void swap(ResponseError<T, TDerived>& arg) noexcept - { + T error; + bool IsErrorType() override { return true; } + void swap(ResponseError<T, TDerived>& arg) noexcept + { - this->id.swap(arg.id); - this->m_methodType.swap(arg.m_methodType); - std::swap(error, arg.error); - } + this->id.swap(arg.id); + this->m_methodType.swap(arg.m_methodType); + std::swap(error, arg.error); + } }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h index f09ba5b1a7..19a9634286 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h @@ -27,7 +27,7 @@ DEALINGS IN THE SOFTWARE. // Taken from https://github.com/cbeck88/visit_struct. // // Usage -// +// // #define PRINT_DOUBLE(x) printf(#x " = %d\n", x); // // MACRO_MAP(PRINT_DOUBLE, 1, 2, 3) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h index 6603f3fb3a..57f4932520 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h @@ -9,26 +9,26 @@ struct LspMessage { public: - std::string jsonrpc = "2.0"; - virtual void ReflectWriter(Writer&) = 0; - - // Send the message to the language client by writing it to stdout. - void Write(std::ostream& out); - - - virtual MethodType GetMethodType() const = 0; - virtual void SetMethodType(MethodType) = 0; - - virtual ~LspMessage()=default; - enum Kind - { - REQUEST_MESSAGE, - RESPONCE_MESSAGE, - NOTIFICATION_MESSAGE - }; - - virtual Kind GetKid() = 0; - virtual std::string ToJson() ; - + std::string jsonrpc = "2.0"; + virtual void ReflectWriter(Writer&) = 0; + + // Send the message to the language client by writing it to stdout. + void Write(std::ostream& out); + + + virtual MethodType GetMethodType() const = 0; + virtual void SetMethodType(MethodType) = 0; + + virtual ~LspMessage()=default; + enum Kind + { + REQUEST_MESSAGE, + RESPONCE_MESSAGE, + NOTIFICATION_MESSAGE + }; + + virtual Kind GetKid() = 0; + virtual std::string ToJson() ; + }; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h index 71b6bede59..477c822845 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h @@ -24,64 +24,64 @@ enum class SerializeFormat { Json, MessagePack }; // A tag type that can be used to write `null` to json. struct JsonNull { - void swap(JsonNull& arg) noexcept; + void swap(JsonNull& arg) noexcept; }; class Reader { public: - virtual ~Reader() {} - virtual SerializeFormat Format() const = 0; - - virtual bool IsBool() = 0; - virtual bool IsNull() = 0; - virtual bool IsArray() = 0; - virtual bool IsInt() = 0; - virtual bool IsInt64() = 0; - virtual bool IsUint64() = 0; - virtual bool IsDouble() = 0; + virtual ~Reader() {} + virtual SerializeFormat Format() const = 0; + + virtual bool IsBool() = 0; + virtual bool IsNull() = 0; + virtual bool IsArray() = 0; + virtual bool IsInt() = 0; + virtual bool IsInt64() = 0; + virtual bool IsUint64() = 0; + virtual bool IsDouble() = 0; virtual bool IsNumber() = 0; virtual bool IsString() = 0; - virtual void GetNull() = 0; - virtual bool GetBool() = 0; - virtual int GetInt() = 0; - virtual uint32_t GetUint32() = 0; - virtual int64_t GetInt64() = 0; - virtual uint64_t GetUint64() = 0; - virtual double GetDouble() = 0; - virtual std::string GetString() = 0; - - virtual bool HasMember(const char* x) = 0; - virtual std::unique_ptr<Reader> operator[](const char* x) = 0; - virtual void IterMap( std::function<void(const char*, Reader&)> fn) = 0; - virtual void IterArray(std::function<void(Reader&)> fn) = 0; - virtual void DoMember(const char* name, std::function<void(Reader&)> fn) = 0; - virtual std::string ToString() const = 0; + virtual void GetNull() = 0; + virtual bool GetBool() = 0; + virtual int GetInt() = 0; + virtual uint32_t GetUint32() = 0; + virtual int64_t GetInt64() = 0; + virtual uint64_t GetUint64() = 0; + virtual double GetDouble() = 0; + virtual std::string GetString() = 0; + + virtual bool HasMember(const char* x) = 0; + virtual std::unique_ptr<Reader> operator[](const char* x) = 0; + virtual void IterMap( std::function<void(const char*, Reader&)> fn) = 0; + virtual void IterArray(std::function<void(Reader&)> fn) = 0; + virtual void DoMember(const char* name, std::function<void(Reader&)> fn) = 0; + virtual std::string ToString() const = 0; }; class Writer { public: - virtual ~Writer() {} - virtual SerializeFormat Format() const = 0; - - virtual void Null() = 0; - virtual void Bool(bool x) = 0; - virtual void Int(int x) = 0; - virtual void Uint32(uint32_t x) = 0; - virtual void Int64(int64_t x) = 0; - virtual void Uint64(uint64_t x) = 0; - virtual void Double(double x) = 0; - virtual void String(const char* x) = 0; - virtual void String(const char* x, size_t len) = 0; - virtual void StartArray(size_t) = 0; - virtual void EndArray() = 0; - virtual void StartObject() = 0; - virtual void EndObject() = 0; - virtual void Key(const char* name) = 0; + virtual ~Writer() {} + virtual SerializeFormat Format() const = 0; + + virtual void Null() = 0; + virtual void Bool(bool x) = 0; + virtual void Int(int x) = 0; + virtual void Uint32(uint32_t x) = 0; + virtual void Int64(int64_t x) = 0; + virtual void Uint64(uint64_t x) = 0; + virtual void Double(double x) = 0; + virtual void String(const char* x) = 0; + virtual void String(const char* x, size_t len) = 0; + virtual void StartArray(size_t) = 0; + virtual void EndArray() = 0; + virtual void StartObject() = 0; + virtual void EndObject() = 0; + virtual void Key(const char* name) = 0; }; @@ -130,9 +130,9 @@ struct optionals_mandatory_tag {}; #define _MAPPABLE_SWAP_MEMBER(name) std::swap(name,arg.name); -#define MAKE_SWAP_METHOD(type, ...) \ -void swap(type& arg) noexcept{ \ - MACRO_MAP(_MAPPABLE_SWAP_MEMBER, __VA_ARGS__) \ +#define MAKE_SWAP_METHOD(type, ...) \ +void swap(type& arg) noexcept{ \ + MACRO_MAP(_MAPPABLE_SWAP_MEMBER, __VA_ARGS__) \ } #define MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(type, ...) \ @@ -208,171 +208,171 @@ void Reflect(Writer& visitor, SerializeFormat& value); template <typename T> void Reflect(Reader& visitor, boost::optional<T>& value) { - if (visitor.IsNull()) { - visitor.GetNull(); - return; - } - T real_value; - Reflect(visitor, real_value); - value = std::move(real_value); + if (visitor.IsNull()) { + visitor.GetNull(); + return; + } + T real_value; + Reflect(visitor, real_value); + value = std::move(real_value); } template <typename T> void Reflect(Writer& visitor, boost::optional<T>& value) { - if (value) - Reflect(visitor, *value); - else - visitor.Null(); + if (value) + Reflect(visitor, *value); + else + visitor.Null(); } template <typename T> void ReflectMember(Writer& visitor, const char* name, boost::optional<T>& value) { - // For TypeScript optional property key?: value in the spec, - // We omit both key and value if value is std::nullopt (null) for JsonWriter - // to reduce output. But keep it for other serialization formats. - if (value || visitor.Format() != SerializeFormat::Json) { - visitor.Key(name); - Reflect(visitor, value); - } + // For TypeScript optional property key?: value in the spec, + // We omit both key and value if value is std::nullopt (null) for JsonWriter + // to reduce output. But keep it for other serialization formats. + if (value || visitor.Format() != SerializeFormat::Json) { + visitor.Key(name); + Reflect(visitor, value); + } } template <typename T> void ReflectMember(Writer& visitor, - const char* name, - T& value, - optionals_mandatory_tag) { - visitor.Key(name); - Reflect(visitor, value); + const char* name, + T& value, + optionals_mandatory_tag) { + visitor.Key(name); + Reflect(visitor, value); } template <typename T> void ReflectMember(Reader& visitor, - const char* name, - T& value, - optionals_mandatory_tag) { - Reflect(visitor, value); + const char* name, + T& value, + optionals_mandatory_tag) { + Reflect(visitor, value); } template<class T > void Reflect(Reader& visitor, std::map<std::string, T>& value) { - visitor.IterMap([&](const char* name,Reader& entry) { - T entry_value; - Reflect(entry, entry_value); - value[name]=(std::move(entry_value)); - }); + visitor.IterMap([&](const char* name,Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + value[name]=(std::move(entry_value)); + }); } template<class _Ty > void Reflect(Writer& visitor, std::map<std::string, _Ty>& value) { - REFLECT_MEMBER_START(); - for (auto& it : value) - { - visitor.Key(it.first.c_str()); - Reflect(visitor, it.second); - } - REFLECT_MEMBER_END(); + REFLECT_MEMBER_START(); + for (auto& it : value) + { + visitor.Key(it.first.c_str()); + Reflect(visitor, it.second); + } + REFLECT_MEMBER_END(); } // std::vector template <typename T> void Reflect(Reader& visitor, std::vector<T>& values) { - visitor.IterArray([&](Reader& entry) { - T entry_value; - Reflect(entry, entry_value); - values.push_back(std::move(entry_value)); - }); + visitor.IterArray([&](Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + values.push_back(std::move(entry_value)); + }); } template <typename T> void Reflect(Writer& visitor, std::vector<T>& values) { - visitor.StartArray(values.size()); - for (auto& value : values) - Reflect(visitor, value); - visitor.EndArray(); + visitor.StartArray(values.size()); + for (auto& value : values) + Reflect(visitor, value); + visitor.EndArray(); } // ReflectMember inline void DefaultReflectMemberStart(Writer& visitor) { - visitor.StartObject(); + visitor.StartObject(); } inline void DefaultReflectMemberStart(Reader& visitor) {} template <typename T> bool ReflectMemberStart(Reader& visitor, T& value) { - return false; + return false; } template <typename T> bool ReflectMemberStart(Writer& visitor, T& value) { - visitor.StartObject(); - return true; + visitor.StartObject(); + return true; } template <typename T> void ReflectMemberEnd(Reader& visitor, T& value) {} template <typename T> void ReflectMemberEnd(Writer& visitor, T& value) { - visitor.EndObject(); + visitor.EndObject(); } template <typename T> void ReflectMember(Reader& visitor, const char* name, T& value) { - visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); + visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); } template <typename T> void ReflectMember(Writer& visitor, const char* name, T& value) { - visitor.Key(name); - Reflect(visitor, value); + visitor.Key(name); + Reflect(visitor, value); } template<class _Ty1, class _Ty2> void Reflect(Writer& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) { - if (value.first) - { - Reflect(visitor, value.first); - } - else - { - Reflect(visitor, value.second); - } + if (value.first) + { + Reflect(visitor, value.first); + } + else + { + Reflect(visitor, value.second); + } } template<class _Ty2> void Reflect(Reader& visitor, std::pair< boost::optional<bool>, boost::optional<_Ty2> >& value) { - if(visitor.IsBool()) - { - Reflect(visitor, value.first); - return; - } + if(visitor.IsBool()) + { + Reflect(visitor, value.first); + return; + } - Reflect(visitor, value.second); + Reflect(visitor, value.second); } template<class _Ty2> void Reflect(Reader& visitor, std::pair< boost::optional<std::string>, boost::optional<_Ty2> >& value) { - if (visitor.IsString()) - { - Reflect(visitor, value.first); - return; - } + if (visitor.IsString()) + { + Reflect(visitor, value.first); + return; + } - Reflect(visitor, value.second); + Reflect(visitor, value.second); } template<class _Ty1, class _Ty2> void Reflect(Reader& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) { - try - { - Reflect(visitor, value.second); - } - catch (...) - { - Reflect(visitor, value.first); - } + try + { + Reflect(visitor, value.second); + } + catch (...) + { + Reflect(visitor, value.first); + } } diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h index 549c361950..3dd3def993 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h @@ -3,194 +3,194 @@ #include <string> namespace lsp { - class stream - { - public: - virtual ~stream() = default; - virtual bool fail() = 0; - virtual bool bad() = 0; - virtual bool eof() = 0; - virtual bool good() = 0; - virtual void clear() = 0; - virtual std::string what() = 0; - virtual bool need_to_clear_the_state() - { - return false; - } - - bool operator!() - { - return bad(); - } - }; - class istream : public stream - { - public: - virtual int get() = 0; - virtual ~istream() = default; - virtual istream& read(char* str, std::streamsize count) = 0; - }; - template <class T > - class base_istream : public istream - { - public: - explicit base_istream(T& _t) :_impl(_t) - { - - } - - int get() override - { - return _impl.get(); - } - bool fail() override - { - return _impl.fail(); - } - bool bad() override - { - return _impl.bad(); - } - bool eof() override - { - return _impl.eof(); - } - bool good() override - { - return _impl.good(); - } - istream& read(char* str, std::streamsize count) override - { - _impl.read(str, count); - return *this; - } - - void clear() override - { - _impl.clear(); - } - T& _impl; - }; - class ostream : public stream - { - public: - virtual ~ostream() = default; - - virtual ostream& write(const std::string&) = 0; - virtual ostream& write(std::streamsize) = 0; - virtual ostream& flush() = 0; - - }; - template <class T > - class base_ostream : public ostream - { - public: - explicit base_ostream(T& _t) :_impl(_t) - { - - } - - bool fail() override - { - return _impl.fail(); - } - bool good() override - { - return _impl.good(); - } - bool bad() override - { - return _impl.bad(); - } - bool eof() override - { - return _impl.eof(); - } - - ostream& write(const std::string& c) override - { - _impl << c; - return *this; - } - - ostream& write(std::streamsize _s) override - { - - _impl << std::to_string(_s); - return *this; - } - - ostream& flush() override - { - _impl.flush(); - return *this; - } - - void clear() override - { - _impl.clear(); - } - protected: - T& _impl; - }; - - template <class T > - class base_iostream : public istream, public ostream - { - public: - explicit base_iostream(T& _t) :_impl(_t) - { - - } - - int get() override - { - return _impl.get(); - } - bool fail() override - { - return _impl.fail(); - } - bool bad() override - { - return _impl.bad(); - } - bool eof() override - { - return _impl.eof(); - } - bool good() override - { - return _impl.good(); - } - istream& read(char* str, std::streamsize count) override - { - _impl.read(str, count); - return *this; - } - ostream& write(const std::string& c) override - { - _impl << c; - return *this; - } - - ostream& write(std::streamsize _s) override - { - _impl << std::to_string(_s); - return *this; - } - - ostream& flush() override - { - _impl.flush(); - return *this; - } - - void clear() override - { - _impl.clear(); - } - protected: - T& _impl; - }; + class stream + { + public: + virtual ~stream() = default; + virtual bool fail() = 0; + virtual bool bad() = 0; + virtual bool eof() = 0; + virtual bool good() = 0; + virtual void clear() = 0; + virtual std::string what() = 0; + virtual bool need_to_clear_the_state() + { + return false; + } + + bool operator!() + { + return bad(); + } + }; + class istream : public stream + { + public: + virtual int get() = 0; + virtual ~istream() = default; + virtual istream& read(char* str, std::streamsize count) = 0; + }; + template <class T > + class base_istream : public istream + { + public: + explicit base_istream(T& _t) :_impl(_t) + { + + } + + int get() override + { + return _impl.get(); + } + bool fail() override + { + return _impl.fail(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + bool good() override + { + return _impl.good(); + } + istream& read(char* str, std::streamsize count) override + { + _impl.read(str, count); + return *this; + } + + void clear() override + { + _impl.clear(); + } + T& _impl; + }; + class ostream : public stream + { + public: + virtual ~ostream() = default; + + virtual ostream& write(const std::string&) = 0; + virtual ostream& write(std::streamsize) = 0; + virtual ostream& flush() = 0; + + }; + template <class T > + class base_ostream : public ostream + { + public: + explicit base_ostream(T& _t) :_impl(_t) + { + + } + + bool fail() override + { + return _impl.fail(); + } + bool good() override + { + return _impl.good(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + + ostream& write(const std::string& c) override + { + _impl << c; + return *this; + } + + ostream& write(std::streamsize _s) override + { + + _impl << std::to_string(_s); + return *this; + } + + ostream& flush() override + { + _impl.flush(); + return *this; + } + + void clear() override + { + _impl.clear(); + } + protected: + T& _impl; + }; + + template <class T > + class base_iostream : public istream, public ostream + { + public: + explicit base_iostream(T& _t) :_impl(_t) + { + + } + + int get() override + { + return _impl.get(); + } + bool fail() override + { + return _impl.fail(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + bool good() override + { + return _impl.good(); + } + istream& read(char* str, std::streamsize count) override + { + _impl.read(str, count); + return *this; + } + ostream& write(const std::string& c) override + { + _impl << c; + return *this; + } + + ostream& write(std::streamsize _s) override + { + _impl << std::to_string(_s); + return *this; + } + + ostream& flush() override + { + _impl.flush(); + return *this; + } + + void clear() override + { + _impl.clear(); + } + protected: + T& _impl; + }; } diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h index cca9f9a486..3e1ba547ca 100644 --- a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h @@ -57,23 +57,23 @@ struct MultiQueueWaiter { static bool HasState(std::initializer_list<BaseThreadQueue*> queues); bool ValidateWaiter(std::initializer_list<BaseThreadQueue*> queues); - + template <typename... BaseThreadQueue> bool Wait(std::atomic<bool>& quit, BaseThreadQueue... queues) { - MultiQueueLock<BaseThreadQueue...> l(queues...); - while (!quit.load(std::memory_order_relaxed)) { - if (HasState({ queues... })) - return false; - cv.wait(l); - } - return true; + MultiQueueLock<BaseThreadQueue...> l(queues...); + while (!quit.load(std::memory_order_relaxed)) { + if (HasState({ queues... })) + return false; + cv.wait(l); + } + return true; } template <typename... BaseThreadQueue> void WaitUntil(std::chrono::steady_clock::time_point t, - BaseThreadQueue... queues) { - MultiQueueLock<BaseThreadQueue...> l(queues...); - if (!HasState({ queues... })) - cv.wait_until(l, t); + BaseThreadQueue... queues) { + MultiQueueLock<BaseThreadQueue...> l(queues...); + if (!HasState({ queues... })) + cv.wait_until(l, t); } template <typename... BaseThreadQueue> void Wait(BaseThreadQueue... queues) { @@ -181,22 +181,22 @@ struct ThreadedQueue : public BaseThreadQueue { } // Return all elements in the queue. std::vector<T> DequeueAll() { - std::lock_guard<std::mutex> lock(mutex); - - total_count_ = 0; - - std::vector<T> result; - result.reserve(priority_.size() + queue_.size()); - while (!priority_.empty()) { - result.emplace_back(std::move(priority_.front())); - priority_.pop_front(); - } - while (!queue_.empty()) { - result.emplace_back(std::move(queue_.front())); - queue_.pop_front(); - } - - return result; + std::lock_guard<std::mutex> lock(mutex); + + total_count_ = 0; + + std::vector<T> result; + result.reserve(priority_.size() + queue_.size()); + while (!priority_.empty()) { + result.emplace_back(std::move(priority_.front())); + priority_.pop_front(); + } + while (!queue_.empty()) { + result.emplace_back(std::move(queue_.front())); + queue_.pop_front(); + } + + return result; } std::vector<T> TryDequeueSome(size_t num) { std::lock_guard<std::mutex> lock(mutex); @@ -213,7 +213,7 @@ struct ThreadedQueue : public BaseThreadQueue { } else { - break; + break; } num -= 1; } |