cmDebuggerPipeConnection.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmConfigure.h" // IWYU pragma: keep
  5. #include <condition_variable>
  6. #include <cstddef>
  7. #include <future>
  8. #include <memory>
  9. #include <mutex>
  10. #include <string>
  11. #include <thread>
  12. #include <cm3p/cppdap/io.h>
  13. #include <cm3p/uv.h>
  14. #include "cmDebuggerAdapter.h"
  15. #include "cmUVHandlePtr.h"
  16. namespace cmDebugger {
  17. class cmDebuggerPipeBase : public dap::ReaderWriter
  18. {
  19. public:
  20. cmDebuggerPipeBase(std::string name);
  21. void WaitForConnection();
  22. // dap::ReaderWriter implementation
  23. void close() final;
  24. size_t read(void* buffer, size_t n) final;
  25. bool write(const void* buffer, size_t n) final;
  26. protected:
  27. virtual void CloseConnection(){};
  28. template <typename T>
  29. void StartReading(uv_stream_t* stream)
  30. {
  31. uv_read_start(
  32. stream,
  33. // alloc_cb
  34. [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
  35. (void)handle;
  36. char* rawBuffer = new char[suggested_size];
  37. *buf =
  38. uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
  39. },
  40. // read_cb
  41. [](uv_stream_t* readStream, ssize_t nread, const uv_buf_t* buf) {
  42. auto conn = static_cast<T*>(readStream->data);
  43. if (conn) {
  44. if (nread >= 0) {
  45. conn->BufferData(std::string(buf->base, buf->base + nread));
  46. } else {
  47. conn->close();
  48. }
  49. }
  50. delete[] (buf->base);
  51. });
  52. }
  53. void StopLoop();
  54. const std::string PipeName;
  55. std::thread LoopThread;
  56. cm::uv_loop_ptr Loop;
  57. cm::uv_pipe_ptr Pipe;
  58. std::mutex Mutex;
  59. std::condition_variable Connected;
  60. bool FailedToOpen = false;
  61. private:
  62. void BufferData(const std::string& data);
  63. void WriteInternal();
  64. cm::uv_async_ptr LoopExit;
  65. cm::uv_async_ptr WriteEvent;
  66. cm::uv_async_ptr PipeClose;
  67. std::string WriteBuffer;
  68. std::string ReadBuffer;
  69. std::condition_variable ReadReady;
  70. std::condition_variable WriteComplete;
  71. };
  72. class cmDebuggerPipeConnection
  73. : public cmDebuggerPipeBase
  74. , public cmDebuggerConnection
  75. , public std::enable_shared_from_this<cmDebuggerPipeConnection>
  76. {
  77. public:
  78. cmDebuggerPipeConnection(std::string name);
  79. ~cmDebuggerPipeConnection() override;
  80. void WaitForConnection() override
  81. {
  82. cmDebuggerPipeBase::WaitForConnection();
  83. }
  84. bool StartListening(std::string& errorMessage) override;
  85. std::shared_ptr<dap::Reader> GetReader() override;
  86. std::shared_ptr<dap::Writer> GetWriter() override;
  87. // dap::ReaderWriter implementation
  88. bool isOpen() override;
  89. // Used for unit test synchronization
  90. std::promise<void> StartedListening;
  91. private:
  92. void CloseConnection() override;
  93. void Connect(uv_stream_t* server);
  94. cm::uv_pipe_ptr ServerPipe;
  95. cm::uv_async_ptr ServerPipeClose;
  96. };
  97. class cmDebuggerPipeClient : public cmDebuggerPipeBase
  98. {
  99. public:
  100. using cmDebuggerPipeBase::cmDebuggerPipeBase;
  101. ~cmDebuggerPipeClient() override;
  102. void Start();
  103. // dap::ReaderWriter implementation
  104. bool isOpen() override;
  105. private:
  106. void CloseConnection() override;
  107. void Connect();
  108. void FailConnection();
  109. bool IsConnected = false;
  110. };
  111. } // namespace cmDebugger