Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/base/io-engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ using namespace icinga;
* @param yc Needed to asynchronously wait for the condition variable.
* @param strand Where to post the wake-up of the condition variable.
*/
CpuBoundWork::CpuBoundWork(boost::asio::yield_context yc, boost::asio::io_context::strand& strand)
CpuBoundWork::CpuBoundWork(boost::asio::yield_context yc, IoStrand& strand)
: m_Done(false)
{
VERIFY(IoEngine::IsStrandRunningOnThisThread(strand));
Expand Down
13 changes: 7 additions & 6 deletions lib/base/io-engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <boost/exception/all.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_context_strand.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>

Expand All @@ -33,6 +32,8 @@
namespace icinga
{

using IoStrand = boost::asio::strand<boost::asio::io_context::executor_type>;

/**
* Scope lock for CPU-bound work done in an I/O thread
*
Expand All @@ -41,7 +42,7 @@
class CpuBoundWork
{
public:
CpuBoundWork(boost::asio::yield_context yc, boost::asio::io_context::strand&);
CpuBoundWork(boost::asio::yield_context yc, IoStrand&);
CpuBoundWork(const CpuBoundWork&) = delete;
CpuBoundWork(CpuBoundWork&&) = delete;
CpuBoundWork& operator=(const CpuBoundWork&) = delete;
Expand Down Expand Up @@ -112,7 +113,7 @@
* [^2]: https://bugs.llvm.org/show_bug.cgi?id=19177
* [^3]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26461
*/
BOOST_NOINLINE static bool IsStrandRunningOnThisThread(const boost::asio::io_context::strand& strand)
BOOST_NOINLINE static bool IsStrandRunningOnThisThread(const IoStrand& strand)
{
return strand.running_in_this_thread();
}
Expand Down Expand Up @@ -175,7 +176,7 @@

std::atomic_uint_fast32_t m_CpuBoundSemaphore;
std::mutex m_CpuBoundWaitingMutex;
std::vector<std::pair<boost::asio::io_context::strand, Shared<AsioConditionVariable>::Ptr>> m_CpuBoundWaiting;
std::vector<std::pair<IoStrand, Shared<AsioConditionVariable>::Ptr>> m_CpuBoundWaiting;
};

class TerminateIoThread : public std::exception
Expand All @@ -197,7 +198,7 @@
void Wait(boost::asio::yield_context yc);

private:
boost::asio::deadline_timer m_Timer;

Check warning on line 201 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / fedora:44

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]

Check warning on line 201 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:26.04

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]
};

/**
Expand Down Expand Up @@ -244,7 +245,7 @@
class Timeout
{
public:
using Timer = boost::asio::deadline_timer;

Check warning on line 248 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / fedora:44

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]

Check warning on line 248 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / fedora:44

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]

Check warning on line 248 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:26.04

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]

Check warning on line 248 in lib/base/io-engine.hpp

View workflow job for this annotation

GitHub Actions / ubuntu:26.04

'boost::asio::deadline_timer' is deprecated: Use system_timer [-Wdeprecated-declarations]

/**
* Schedules onTimeout to be triggered after timeoutFromNow on strand.
Expand All @@ -255,8 +256,8 @@
* @param onTimeout The callback to invoke when the timeout occurs.
*/
template<class OnTimeout>
Timeout(boost::asio::io_context::strand& strand, const Timer::duration_type& timeoutFromNow, OnTimeout onTimeout)
: m_Timer(strand.context(), timeoutFromNow), m_Cancelled(Shared<Atomic<bool>>::Make(false))
Timeout(IoStrand& strand, const Timer::duration_type& timeoutFromNow, OnTimeout onTimeout)
: m_Timer(strand.get_inner_executor().context(), timeoutFromNow), m_Cancelled(Shared<Atomic<bool>>::Make(false))
{
ASSERT(IoEngine::IsStrandRunningOnThisThread(strand));

Expand Down
2 changes: 1 addition & 1 deletion lib/base/tlsstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void AsioTlsStream::ForceDisconnect()
* @param strand Asio strand used for other operations on this connection.
* @param yc Yield context for Asio coroutines
*/
void AsioTlsStream::GracefulDisconnect(boost::asio::io_context::strand& strand, boost::asio::yield_context& yc)
void AsioTlsStream::GracefulDisconnect(IoStrand& strand, boost::asio::yield_context& yc)
{
if (!lowest_layer().is_open()) {
// Already disconnected, nothing to do.
Expand Down
3 changes: 2 additions & 1 deletion lib/base/tlsstream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define TLSSTREAM_H

#include "base/i2-base.hpp"
#include "base/io-engine.hpp"
#include "base/shared.hpp"
#include "base/socket.hpp"
#include "base/stream.hpp"
Expand Down Expand Up @@ -114,7 +115,7 @@ class AsioTlsStream : public boost::asio::buffered_stream<UnbufferedAsioTlsStrea
}

void ForceDisconnect();
void GracefulDisconnect(boost::asio::io_context::strand& strand, boost::asio::yield_context& yc);
void GracefulDisconnect(IoStrand& strand, boost::asio::yield_context& yc);

private:
inline
Expand Down
10 changes: 5 additions & 5 deletions lib/icingadb/redisconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ RedisConnection::RedisConnection(
bool trackOwnPendingQueries
)
: m_ConnInfo{connInfo},
m_Strand(io),
m_Strand(io.get_executor()),
m_Connecting(false),
m_Connected(false),
m_Started(false),
Expand Down Expand Up @@ -285,7 +285,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
{
Defer notConnecting ([this]() { m_Connecting.store(m_Connected.load()); });

boost::asio::deadline_timer timer (m_Strand.context());
boost::asio::deadline_timer timer (m_Strand.get_inner_executor().context());

for (;;) {
try {
Expand All @@ -294,7 +294,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
Log(m_Parent ? LogNotice : LogInformation, "IcingaDB")
<< "Trying to connect to Redis server (async, TLS) on host '" << m_ConnInfo->Host << ":" << m_ConnInfo->Port << "'";

auto conn (Shared<AsioTlsStream>::Make(m_Strand.context(), *m_TLSContext, m_ConnInfo->Host));
auto conn (Shared<AsioTlsStream>::Make(m_Strand.get_inner_executor().context(), *m_TLSContext, m_ConnInfo->Host));
auto& tlsConn (conn->next_layer());
auto connectTimeout (MakeTimeout(conn));

Expand Down Expand Up @@ -324,7 +324,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
Log(m_Parent ? LogNotice : LogInformation, "IcingaDB")
<< "Trying to connect to Redis server (async) on host '" << m_ConnInfo->Host << ":" << m_ConnInfo->Port << "'";

auto conn (Shared<TcpConn>::Make(m_Strand.context()));
auto conn (Shared<TcpConn>::Make(m_Strand.get_inner_executor().context()));
auto connectTimeout (MakeTimeout(conn));

icinga::Connect(conn->next_layer(), m_ConnInfo->Host, Convert::ToString(m_ConnInfo->Port), yc);
Expand All @@ -336,7 +336,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
Log(LogInformation, "IcingaDB")
<< "Trying to connect to Redis server (async) on unix socket path '" << m_ConnInfo->Path << "'";

auto conn (Shared<UnixConn>::Make(m_Strand.context()));
auto conn (Shared<UnixConn>::Make(m_Strand.get_inner_executor().context()));
auto connectTimeout (MakeTimeout(conn));

conn->next_layer().async_connect(Unix::endpoint(m_ConnInfo->Path.CStr()), yc);
Expand Down
3 changes: 1 addition & 2 deletions lib/icingadb/redisconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <boost/asio/buffered_stream.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_context_strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/local/stream_protocol.hpp>
#include <boost/asio/read.hpp>
Expand Down Expand Up @@ -289,7 +288,7 @@ struct RedisConnInfo final : SharedObject

RedisConnInfo::ConstPtr m_ConnInfo; // Redis connection info (immutable)

boost::asio::io_context::strand m_Strand;
IoStrand m_Strand;
Shared<TcpConn>::Ptr m_TcpConn;
Shared<UnixConn>::Ptr m_UnixConn;
Shared<AsioTlsStream>::Ptr m_TlsConn;
Expand Down
2 changes: 1 addition & 1 deletion lib/methods/ifwapichecktask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ void IfwApiCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes
}

auto& io (IoEngine::Get().GetIoContext());
auto strand (Shared<asio::io_context::strand>::Make(io));
auto strand (std::make_shared<IoStrand>(io.get_executor()));
Shared<asio::ssl::context>::Ptr ctx;

cr->SetExecutionStart(Utility::GetTime());
Expand Down
6 changes: 3 additions & 3 deletions lib/otel/otel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ OTel::OTel(OTelConnInfo& connInfo): OTel{connInfo, IoEngine::Get().GetIoContext(

OTel::OTel(OTelConnInfo& connInfo, boost::asio::io_context& io)
: m_ConnInfo{std::move(connInfo)},
m_Strand{io},
m_Strand{io.get_executor()},
m_ExportAsioCV{io},
m_RetryExportAndConnTimer{io},
m_Exporting{false},
Expand Down Expand Up @@ -241,9 +241,9 @@ void OTel::Connect(boost::asio::yield_context& yc)
try {
decltype(m_Stream) stream;
if (m_ConnInfo.EnableTls) {
stream = Shared<AsioTlsStream>::Make(m_Strand.context(), *m_TlsContext, m_ConnInfo.Host);
stream = Shared<AsioTlsStream>::Make(m_Strand.get_inner_executor().context(), *m_TlsContext, m_ConnInfo.Host);
} else {
stream = Shared<AsioTcpStream>::Make(m_Strand.context());
stream = Shared<AsioTcpStream>::Make(m_Strand.get_inner_executor().context());
}

Timeout timeout{m_Strand, boost::posix_time::seconds(10), [this, stream] {
Expand Down
2 changes: 1 addition & 1 deletion lib/otel/otel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class OTel : public SharedObject
const OTelConnInfo m_ConnInfo;
std::optional<AsioTlsOrTcpStream> m_Stream;
Shared<boost::asio::ssl::context>::Ptr m_TlsContext;
boost::asio::io_context::strand m_Strand;
IoStrand m_Strand;

AsioConditionVariable m_ExportAsioCV; // Event to signal when a new export request is available.
// Timer for scheduling retries of failed exports and reconnection attempts.
Expand Down
2 changes: 1 addition & 1 deletion lib/perfdata/perfdatawriterconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ PerfdataWriterConnection::PerfdataWriterConnection(
m_Host(std::move(host)),
m_Port(std::move(port)),
m_ReconnectTimer(IoEngine::Get().GetIoContext()),
m_Strand(IoEngine::Get().GetIoContext()),
m_Strand(IoEngine::Get().GetIoContext().get_executor()),
m_Stream(MakeStream())
{
}
Expand Down
2 changes: 1 addition & 1 deletion lib/perfdata/perfdatawriterconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class PerfdataWriterConnection final : public Object

std::chrono::milliseconds m_RetryTimeout{InitialRetryWait};
boost::asio::steady_timer m_ReconnectTimer;
boost::asio::io_context::strand m_Strand;
IoStrand m_Strand;
AsioTlsOrTcpStream m_Stream;
};

Expand Down
11 changes: 5 additions & 6 deletions lib/remote/apilistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include "base/exception.hpp"
#include "base/tcpsocket.hpp"
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context_strand.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ssl/context.hpp>
Expand Down Expand Up @@ -493,7 +492,7 @@ bool ApiListener::AddListener(const String& node, const String& service)
Log(LogInformation, "ApiListener")
<< "Started new listener on '[" << localEndpoint.address() << "]:" << localEndpoint.port() << "'";

auto strand = Shared<asio::io_context::strand>::Make(io);
auto strand = std::make_shared<IoStrand>(io.get_executor());

boost::signals2::scoped_connection closeSignal = m_OnListenerShutdown.connect([strand, acceptor]() {
boost::asio::post(*strand, [acceptor] {
Expand Down Expand Up @@ -569,7 +568,7 @@ void ApiListener::ListenerCoroutineProc(boost::asio::yield_context yc, const Sha
lock.unlock();
sslConn->lowest_layer() = std::move(socket);

auto strand (Shared<asio::io_context::strand>::Make(io));
auto strand = std::make_shared<IoStrand>(io.get_executor());

IoEngine::SpawnCoroutine(*strand, [this, strand, sslConn, remoteEndpoint](asio::yield_context yc) {
Timeout timeout (*strand, boost::posix_time::microseconds(int64_t(GetConnectTimeout() * 1e6)),
Expand Down Expand Up @@ -613,7 +612,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
}

auto& io (IoEngine::Get().GetIoContext());
auto strand (Shared<asio::io_context::strand>::Make(io));
auto strand = std::make_shared<IoStrand>(io.get_executor());

IoEngine::SpawnCoroutine(*strand, [this, strand, endpoint, &io](asio::yield_context yc) {
String host = endpoint->GetHost();
Expand Down Expand Up @@ -656,7 +655,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
}

void ApiListener::NewClientHandler(
boost::asio::yield_context yc, const Shared<boost::asio::io_context::strand>::Ptr& strand,
boost::asio::yield_context yc, const std::shared_ptr<IoStrand>& strand,
const Shared<AsioTlsStream>::Ptr& client, const String& hostname, ConnectionRole role
)
{
Expand Down Expand Up @@ -691,7 +690,7 @@ static const auto l_AppVersionInt (([]() -> unsigned long {
* @param client The new client.
*/
void ApiListener::NewClientHandlerInternal(
boost::asio::yield_context yc, const Shared<boost::asio::io_context::strand>::Ptr& strand,
boost::asio::yield_context yc, const std::shared_ptr<IoStrand>& strand,
const Shared<AsioTlsStream>::Ptr& client, const String& hostname, ConnectionRole role
)
{
Expand Down
5 changes: 3 additions & 2 deletions lib/remote/apilistener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <boost/asio/ssl/context.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <cstdint>
#include <memory>
#include <mutex>
#include <set>

Expand Down Expand Up @@ -209,11 +210,11 @@ class ApiListener final : public ObjectImpl<ApiListener>
void AddConnection(const Endpoint::Ptr& endpoint);

void NewClientHandler(
boost::asio::yield_context yc, const Shared<boost::asio::io_context::strand>::Ptr& strand,
boost::asio::yield_context yc, const std::shared_ptr<IoStrand>& strand,
const Shared<AsioTlsStream>::Ptr& client, const String& hostname, ConnectionRole role
);
void NewClientHandlerInternal(
boost::asio::yield_context yc, const Shared<boost::asio::io_context::strand>::Ptr& strand,
boost::asio::yield_context yc, const std::shared_ptr<IoStrand>& strand,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the std::shared_ptr?

@jschmidt-icinga jschmidt-icinga Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a section to the PR description about the reason. In short, it's because on older boost versions boost::asio::spawn() don't know what to do with the Shared<strand>& it gets as a result of dereferencing the pointer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion we should consider deprecating it and just use std::shared_ptr

Absolutely not. I introduced it specifically to save memory. We already had enough memory problems in the past, didn't we?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What memory does Shared<> save vs. std::shared_ptr<>? 🤔
It will save an additional allocation for the reference count in case someone doesn't use std::make_shared() as one should anyways. And in the rare cases where std::shared_from_this is actually needed, I think it stores an additional std::weak_ptr, but that's negligible for most our classes. At first glance I don't even see anything that would require the latter... we mostly use Shared<> for Stream objects, SSL context and things like that. std::shared_ptr should be perfectly fine for those, or am I missing something.

To be clear: I'm not saying deprecate boost::intrusive_ptr for our Object::Ptr, just shoehorning it into a generic shared pointer, which it was never meant to be.

const Shared<AsioTlsStream>::Ptr& client, const String& hostname, ConnectionRole role
);
void ListenerCoroutineProc(boost::asio::yield_context yc, const Shared<boost::asio::ip::tcp::acceptor>::Ptr& server);
Expand Down
2 changes: 1 addition & 1 deletion lib/remote/httpmessage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ class OutgoingHttpMessage : public boost::beast::http::message<isRequest, Body>
* @param yc Yield context that is used for waiting.
* @param strand Strand the caller is running on, used for synchronization.
*/
void StartCpuBoundWork(boost::asio::yield_context yc, boost::asio::io_context::strand& strand)
void StartCpuBoundWork(boost::asio::yield_context yc, IoStrand& strand)
{
m_CpuBoundWork.emplace(yc, strand);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/remote/httpserverconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ HttpServerConnection::HttpServerConnection(const WaitGroup::Ptr& waitGroup, cons
}

HttpServerConnection::HttpServerConnection(const WaitGroup::Ptr& waitGroup, const String& identity, bool authenticated, const Shared<AsioTlsStream>::Ptr& stream, boost::asio::io_context& io)
: m_WaitGroup(waitGroup), m_Stream(stream), m_IoStrand(io), m_ShuttingDown(false), m_ConnectionReusable(true), m_CheckLivenessTimer(io)
: m_WaitGroup(waitGroup), m_Stream(stream), m_IoStrand(io.get_executor()), m_ShuttingDown(false), m_ConnectionReusable(true), m_CheckLivenessTimer(io)
{
if (authenticated) {
m_ApiUser = ApiUser::GetByClientCN(identity);
Expand Down Expand Up @@ -419,7 +419,7 @@ void ProcessRequest(
const WaitGroup::Ptr& waitGroup,
std::chrono::steady_clock::duration& cpuBoundWorkTime,
boost::asio::yield_context& yc,
boost::asio::io_context::strand& strand
IoStrand& strand
)
{
try {
Expand Down
4 changes: 2 additions & 2 deletions lib/remote/httpserverconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
#define HTTPSERVERCONNECTION_H

#include "remote/apiuser.hpp"
#include "base/io-engine.hpp"
#include "base/string.hpp"
#include "base/tlsstream.hpp"
#include "base/wait-group.hpp"
#include <memory>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_context_strand.hpp>
#include <boost/asio/spawn.hpp>
#include <chrono>

Expand Down Expand Up @@ -55,7 +55,7 @@ class HttpServerConnection final : public Object
std::chrono::steady_clock::time_point m_Seen{std::chrono::steady_clock::now()};
std::chrono::milliseconds m_LivenessTimeout{10s};
String m_PeerAddress;
boost::asio::io_context::strand m_IoStrand;
IoStrand m_IoStrand;
bool m_ShuttingDown;
bool m_ConnectionReusable;
boost::asio::deadline_timer m_CheckLivenessTimer;
Expand Down
2 changes: 1 addition & 1 deletion lib/remote/jsonrpcconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ JsonRpcConnection::JsonRpcConnection(const WaitGroup::Ptr& waitGroup, const Stri
JsonRpcConnection::JsonRpcConnection(const WaitGroup::Ptr& waitGroup, const String& identity, bool authenticated,
const Shared<AsioTlsStream>::Ptr& stream, ConnectionRole role, boost::asio::io_context& io)
: m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), m_Role(role),
m_Timestamp(Utility::GetTime()), m_Seen(Utility::GetTime()), m_IoStrand(io),
m_Timestamp(Utility::GetTime()), m_Seen(Utility::GetTime()), m_IoStrand(io.get_executor()),
m_OutgoingMessagesQueued(io), m_WriterDone(io), m_ShuttingDown(false), m_WaitGroup(waitGroup),
m_CheckLivenessTimer(io), m_HeartbeatTimer(io)
{
Expand Down
3 changes: 1 addition & 2 deletions lib/remote/jsonrpcconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <memory>
#include <vector>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_context_strand.hpp>
#include <boost/asio/spawn.hpp>

namespace icinga
Expand Down Expand Up @@ -76,7 +75,7 @@ class JsonRpcConnection final : public Object
ConnectionRole m_Role;
double m_Timestamp;
double m_Seen;
boost::asio::io_context::strand m_IoStrand;
IoStrand m_IoStrand;
std::vector<String> m_OutgoingMessagesQueue;
AsioEvent m_OutgoingMessagesQueued;
AsioEvent m_WriterDone;
Expand Down
Loading
Loading