mirror of
https://github.com/matrix-construct/construct
synced 2024-06-02 10:08:56 +02:00
ircd: Make asio header; comments; add special continuation for yielding to asio.
This commit is contained in:
parent
a9ac3f9956
commit
7f548cee1c
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
#include <ircd/ircd.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <ircd/asio.h>
|
||||
#include "lgetopt.h"
|
||||
#include "charybdis.h"
|
||||
|
||||
|
@ -62,11 +62,11 @@ lgetopt opts[] =
|
|||
{ nullptr, nullptr, lgetopt::STRING, nullptr },
|
||||
};
|
||||
|
||||
boost::asio::io_service *ios
|
||||
std::unique_ptr<boost::asio::io_service> ios
|
||||
{
|
||||
// Having trouble with static destruction in clang so this
|
||||
// has to become still-reachable
|
||||
new boost::asio::io_service
|
||||
std::make_unique<boost::asio::io_service>()
|
||||
};
|
||||
|
||||
boost::asio::signal_set sigs
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
// charybdis.cc
|
||||
//
|
||||
|
||||
extern boost::asio::io_service *ios;
|
||||
extern std::unique_ptr<boost::asio::io_service> ios;
|
||||
|
||||
//
|
||||
// console.cc
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
*/
|
||||
|
||||
#include <ircd/ircd.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <ircd/ctx/continuation.h>
|
||||
#include <ircd/asio.h>
|
||||
#include <ircd/m.h>
|
||||
#include "charybdis.h"
|
||||
|
||||
|
@ -163,7 +162,7 @@ try
|
|||
// so the output of the command (if log messages) can be seen.
|
||||
{
|
||||
const log::console_quiet quiet(false);
|
||||
boost::asio::async_read_until(in, buf, '\n', yield_context{continuation{}});
|
||||
boost::asio::async_read_until(in, buf, '\n', yield_context{to_asio{}});
|
||||
}
|
||||
|
||||
std::getline(is, line);
|
||||
|
|
54
include/ircd/asio.h
Normal file
54
include/ircd/asio.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* charybdis: standing on the shoulders of giant build times
|
||||
*
|
||||
* Copyright (C) 2017 Charybdis Development Team
|
||||
* Copyright (C) 2017 Jason Volk <jason@zemos.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice is present in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_ASIO_H
|
||||
|
||||
///
|
||||
/// Boost library
|
||||
///
|
||||
/// It is better to add a boost header which we have omitted here rather than
|
||||
/// in your definition file, and then #include <ircd/asio.h>. This is because
|
||||
/// we can compose a precompiled header for your definition file much easier
|
||||
/// this way.
|
||||
///
|
||||
/// Note that there is no precompile for this header right now, only the
|
||||
/// standard headers. That still significantly improves compile times of these
|
||||
/// boost headers for the time being...
|
||||
///
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
///
|
||||
/// The following IRCd headers are not included in the main stdinc.h list of
|
||||
/// includes because they require boost directly or symbols which we cannot
|
||||
/// forward declare. You should include this in your definition file if you
|
||||
/// need these low-level interfaces.
|
||||
///
|
||||
|
||||
#include <ircd/ctx/continuation.h>
|
||||
#include <ircd/socket.h>
|
|
@ -22,6 +22,15 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_BUFFER_H
|
||||
|
||||
// Forward declarations from boost::asio because it is not included here. IRCd
|
||||
// buffers are not based directly on the boost ones but are easily converted
|
||||
// when passing our buffer to an asio function.
|
||||
namespace boost::asio
|
||||
{
|
||||
struct const_buffer;
|
||||
struct mutable_buffer;
|
||||
}
|
||||
|
||||
/// Lightweight buffer interface compatible with boost::asio IO buffers and vectors
|
||||
///
|
||||
/// A const_buffer is a pair of iterators like `const char *` meant for sending
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
/// Several low-level functions are exposed for library creators. This file is usually
|
||||
/// included when boost/asio.hpp is also included and calls are actually made into boost.
|
||||
///
|
||||
/// boost::asio is not included from here. To access that include boost in a
|
||||
/// definition file with #include <ircd/asio.h>. That include contains some
|
||||
/// devices we use to yield a context to asio.
|
||||
///
|
||||
namespace ircd::ctx
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
|
|
|
@ -22,25 +22,37 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_CONTINUATION_H
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
/// This file is not included with the IRCd standard include stack because
|
||||
/// it requires symbols we can't forward declare without boost headers. It
|
||||
/// is part of the <ircd/asio.h> stack which can be included in your
|
||||
/// definition file if necessary.
|
||||
|
||||
namespace ircd::ctx
|
||||
{
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
struct continuation;
|
||||
struct to_asio;
|
||||
}
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
using ctx::yield_context;
|
||||
using ctx::continuation;
|
||||
using ctx::to_asio;
|
||||
}
|
||||
|
||||
/// This object is placed on the top of the stack when the context is yielding (INTERNAL USE).
|
||||
/// This object must be placed on the stack when the context is yielding (INTERNAL)
|
||||
///
|
||||
/// The continuation constructor is the last thing executed before a context yields.
|
||||
/// The continuation destructor is the first thing executed when a context continues.
|
||||
/// The continuation constructor is the last thing executed before a context
|
||||
/// yields. The continuation destructor is the first thing executed when a
|
||||
/// context continues. This is not placed by a normal user wishing to context
|
||||
/// switch, only a low-level library creator actually implementing the context
|
||||
/// switch itself. The placement of this object must be correct. Generally,
|
||||
/// we construct the `continuation` as an argument to `yield_context` as such
|
||||
/// `yield_context{continuation{}}`. This ensures the continuation destructor
|
||||
/// executes before control continues beyond the yield_context call itself and
|
||||
/// ties this sequence together neatly.
|
||||
///
|
||||
struct ircd::ctx::continuation
|
||||
{
|
||||
|
@ -52,3 +64,18 @@ struct ircd::ctx::continuation
|
|||
continuation(ctx *const &self = ircd::ctx::current);
|
||||
~continuation() noexcept;
|
||||
};
|
||||
|
||||
/// This type of continuation should be used when yielding a context to a
|
||||
/// boost::asio handler so we can have specific control over that type of
|
||||
/// context switch in possible contrast or extension of the regular
|
||||
/// continuation behavior.
|
||||
///
|
||||
/// The statement `yield_context{to_asio{}}` can be passed to any boost::asio
|
||||
/// callback handler. Those handlers have overloads to accept this, many of
|
||||
/// which are not documented.
|
||||
///
|
||||
struct ircd::ctx::to_asio
|
||||
:ircd::ctx::continuation
|
||||
{
|
||||
using continuation::continuation;
|
||||
};
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CLIENT_SOCKET_H
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include "ctx/continuation.h"
|
||||
/// This file is not included with the IRCd standard include stack because
|
||||
/// it requires symbols we can't forward declare without boost headers. It
|
||||
/// is part of the <ircd/asio.h> stack which can be included in your
|
||||
/// definition file if you need low level access to this socket API. The
|
||||
/// client.h still offers higher level access to sockets without requiring
|
||||
/// boost headers; please check that for satisfaction before including this.
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
|
@ -185,7 +187,7 @@ ircd::socket::write(const iov &bufs)
|
|||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
return async_write(ssl, bufs, asio::transfer_all(), yield_context{continuation{}});
|
||||
return async_write(ssl, bufs, asio::transfer_all(), yield_context{to_asio{}});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -196,7 +198,7 @@ ircd::socket::write(const iov &bufs,
|
|||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
return async_write(ssl, bufs, asio::transfer_all(), yield_context{continuation{}}[ec]);
|
||||
return async_write(ssl, bufs, asio::transfer_all(), yield_context{to_asio{}}[ec]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -206,7 +208,7 @@ ircd::socket::write_some(const iov &bufs)
|
|||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
return ssl.async_write_some(bufs, yield_context{continuation{}});
|
||||
return ssl.async_write_some(bufs, yield_context{to_asio{}});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -217,7 +219,7 @@ ircd::socket::write_some(const iov &bufs,
|
|||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
return ssl.async_write_some(bufs, yield_context{continuation{}}[ec]);
|
||||
return ssl.async_write_some(bufs, yield_context{to_asio{}}[ec]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -227,7 +229,7 @@ ircd::socket::read(const iov &bufs)
|
|||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
const size_t ret(async_read(ssl, bufs, yield_context{continuation{}}));
|
||||
const size_t ret(async_read(ssl, bufs, yield_context{to_asio{}}));
|
||||
|
||||
if(unlikely(!ret))
|
||||
throw boost::system::system_error(boost::asio::error::eof);
|
||||
|
@ -243,7 +245,7 @@ ircd::socket::read(const iov &bufs,
|
|||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
return async_read(ssl, bufs, yield_context{continuation{}}[ec]);
|
||||
return async_read(ssl, bufs, yield_context{to_asio{}}[ec]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -253,7 +255,7 @@ ircd::socket::read_some(const iov &bufs)
|
|||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
const size_t ret(ssl.async_read_some(bufs, yield_context{continuation{}}));
|
||||
const size_t ret(ssl.async_read_some(bufs, yield_context{to_asio{}}));
|
||||
|
||||
if(unlikely(!ret))
|
||||
throw boost::system::system_error(boost::asio::error::eof);
|
||||
|
@ -269,6 +271,6 @@ ircd::socket::read_some(const iov &bufs,
|
|||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
return ssl.async_read_some(bufs, yield_context{continuation{}}[ec]);
|
||||
return ssl.async_read_some(bufs, yield_context{to_asio{}}[ec]);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_SPIRIT_H
|
||||
|
||||
/// This file is not part of the IRCd standard include list (stdinc.h) because
|
||||
/// it involves extremely expensive boost headers for creating formal spirit
|
||||
/// grammars. Include this in a definition file which defines such grammars.
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
// by doing things this way and C++ std headers have very little namespace
|
||||
// pollution and risk of conflicts.
|
||||
//
|
||||
// * If any project header file requires standard library symbols we list it
|
||||
// here, not in our header files.
|
||||
// * If any project header file requires standard library symbols we try to
|
||||
// list it here, not in our header files.
|
||||
//
|
||||
// * Rare one-off's #includes isolated to a specific .cc file may not always be
|
||||
// listed here but can be.
|
||||
|
@ -51,6 +51,8 @@
|
|||
// we require a symbol in our API to them.
|
||||
//
|
||||
|
||||
#define HAVE_IRCD_STDINC_H
|
||||
|
||||
// Generated by ./configure
|
||||
#include "config.h"
|
||||
|
||||
|
@ -155,12 +157,11 @@ namespace boost
|
|||
/// Forward declarations for boost::asio because it is not included here.
|
||||
///
|
||||
/// Boost headers are not exposed to our users unless explicitly included by a
|
||||
/// definition file.
|
||||
/// definition file. Other libircd headers may extend this namespace with more
|
||||
/// forward declarations.
|
||||
namespace boost::asio
|
||||
{
|
||||
struct io_service; // Allow a reference to an ios to be passed to ircd
|
||||
struct const_buffer; // ircd/buffer.h
|
||||
struct mutable_buffer; // ircd/buffer.h
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
#include <ircd/socket.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
namespace ircd {
|
||||
|
||||
|
@ -43,11 +43,6 @@ const auto request_timeout
|
|||
300s
|
||||
};
|
||||
|
||||
// Instance of socket::init is constructed and destructed manually to be in sync
|
||||
// with client::init. This is placed here so ircd::main() doesn't have to see
|
||||
// ircd/socket.h and do it there. It should be empty during static destruction.
|
||||
std::unique_ptr<socket::init> socket_init;
|
||||
|
||||
// The pool of request contexts. When a client makes a request it does so by acquiring
|
||||
// a stack from this pool. The request handling and response logic can then be written
|
||||
// in a synchronous manner as if each connection had its own thread.
|
||||
|
@ -76,18 +71,20 @@ template<class... args> std::shared_ptr<client> make_client(args&&...);
|
|||
|
||||
ircd::client::init::init()
|
||||
{
|
||||
assert(!socket_init);
|
||||
socket_init = std::make_unique<socket::init>();
|
||||
request.add(1);
|
||||
request.add(2);
|
||||
}
|
||||
|
||||
ircd::client::init::~init()
|
||||
noexcept
|
||||
{
|
||||
log::debug("Interrupting %zu requests; dropping %zu requests; disconnecting %zu clients.",
|
||||
request.active(),
|
||||
request.pending(),
|
||||
client::clients.size());
|
||||
|
||||
request.interrupt();
|
||||
disconnect_all();
|
||||
request.join();
|
||||
socket_init.reset(nullptr);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <ircd/ctx/continuation.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
|
@ -159,7 +158,7 @@ ircd::ctx::ctx::wait()
|
|||
return false;
|
||||
|
||||
boost::system::error_code ec;
|
||||
alarm.async_wait(boost::asio::yield_context(continuation(this))[ec]);
|
||||
alarm.async_wait(boost::asio::yield_context{to_asio{this}}[ec]);
|
||||
|
||||
assert(ec == errc::operation_canceled || ec == errc::success);
|
||||
assert(current == this);
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <ircd/asio.h>
|
||||
#include <ircd/m.h>
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
|
@ -105,7 +106,8 @@ try
|
|||
// itself if either are more appropriate.
|
||||
|
||||
ctx::ole::init _ole_; // Thread OffLoad Engine
|
||||
client::init _client_; // Client/Socket Networking
|
||||
socket::init _socket_; // Socket/Networking
|
||||
client::init _client_; // Client related
|
||||
db::init _db_; // RocksDB
|
||||
js::init _js_; // SpiderMonkey
|
||||
m::init _matrix_; // Matrix
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ircd/socket.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
namespace ircd {
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ircd/ctx/continuation.h>
|
||||
#include <ircd/socket.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -89,7 +88,7 @@ ircd::socket::socket(const std::string &host,
|
|||
{
|
||||
assert(resolver);
|
||||
const ip::tcp::resolver::query query(host, string(lex_cast(port)));
|
||||
auto epit(resolver->async_resolve(query, yield_context{continuation{}}));
|
||||
auto epit(resolver->async_resolve(query, yield_context{to_asio{}}));
|
||||
static const ip::tcp::resolver::iterator end;
|
||||
if(epit == end)
|
||||
throw nxdomain("host '%s' not found", host.data());
|
||||
|
@ -143,8 +142,8 @@ ircd::socket::connect(const ip::tcp::endpoint &ep,
|
|||
const milliseconds &timeout)
|
||||
{
|
||||
const scope_timeout ts(*this, timeout);
|
||||
sd.async_connect(ep, yield_context{continuation{}});
|
||||
ssl.async_handshake(socket::handshake_type::client, yield_context{continuation{}});
|
||||
sd.async_connect(ep, yield_context{to_asio{}});
|
||||
ssl.async_handshake(socket::handshake_type::client, yield_context{to_asio{}});
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -179,7 +178,7 @@ ircd::socket::disconnect(const dc &type)
|
|||
|
||||
case dc::SSL_NOTIFY_YIELD:
|
||||
{
|
||||
ssl.async_shutdown(yield_context{continuation{}});
|
||||
ssl.async_shutdown(yield_context{to_asio{}});
|
||||
sd.close();
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue