mirror of
https://github.com/matrix-construct/construct
synced 2025-04-29 13:04:17 +02:00
ircd: Employ namespace scope extensions from c++1z/gnu++14.
This is not a move to c++17. If the compiler happens to have support for c++17 namespace scope resolution, they have been kind enough to backport it to gnu++14. This limits our support for really old c++14 compilers, but that was limited anyway. GCC 6.1 and clang 3.6 tested.
This commit is contained in:
parent
28cf226c3a
commit
d9a4f06bf6
54 changed files with 1427 additions and 1457 deletions
include/ircd
allocator.hbuffer.hclient.hcolor.hctx.h
ctx
async.hcontext.hcontinuation.hctx.hdock.hfuture.hmutex.hole.hpool.hprof.hpromise.hqueue.hshared_state.h
db.hdb
exception.hfmt.hfs.hhttp.hinfo.hircd.hjson.hjson
lexical.hlife_guard.hlisten.hlocalee.hlogger.hmapi.hmods.hparams.hparse.hrand.hresource.hsocket.hstdinc.htimer.hircd
|
@ -26,16 +26,19 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_ALLOCATOR_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
struct allocator;
|
||||
}
|
||||
|
||||
struct allocator
|
||||
struct ircd::allocator
|
||||
{
|
||||
struct state;
|
||||
template<class T = char> struct dynamic;
|
||||
template<class T = char, size_t = 512> struct fixed;
|
||||
};
|
||||
|
||||
struct allocator::state
|
||||
struct ircd::allocator::state
|
||||
{
|
||||
using word_t = unsigned long long;
|
||||
using size_type = std::size_t;
|
||||
|
@ -66,7 +69,7 @@ struct allocator::state
|
|||
|
||||
template<class T,
|
||||
size_t max>
|
||||
struct allocator::fixed
|
||||
struct ircd::allocator::fixed
|
||||
:state
|
||||
{
|
||||
struct allocator;
|
||||
|
@ -84,7 +87,7 @@ struct allocator::fixed
|
|||
};
|
||||
|
||||
template<class T>
|
||||
struct allocator::dynamic
|
||||
struct ircd::allocator::dynamic
|
||||
:state
|
||||
{
|
||||
struct allocator;
|
||||
|
@ -116,7 +119,7 @@ struct allocator::dynamic
|
|||
|
||||
template<class T,
|
||||
size_t size>
|
||||
struct allocator::fixed<T, size>::allocator
|
||||
struct ircd::allocator::fixed<T, size>::allocator
|
||||
{
|
||||
using value_type = T;
|
||||
using pointer = T *;
|
||||
|
@ -174,7 +177,7 @@ struct allocator::fixed<T, size>::allocator
|
|||
};
|
||||
|
||||
template<class T>
|
||||
struct allocator::dynamic<T>::allocator
|
||||
struct ircd::allocator::dynamic<T>::allocator
|
||||
{
|
||||
using value_type = T;
|
||||
using pointer = T *;
|
||||
|
@ -231,8 +234,6 @@ struct allocator::dynamic<T>::allocator
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
template<class T>
|
||||
typename ircd::allocator::dynamic<T>::allocator
|
||||
ircd::allocator::dynamic<T>::operator()()
|
||||
|
|
|
@ -22,11 +22,56 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_BUFFER_H
|
||||
|
||||
namespace ircd {
|
||||
namespace buffer {
|
||||
namespace ircd::buffer
|
||||
{
|
||||
template<class it> struct buffer;
|
||||
struct const_buffer;
|
||||
struct mutable_buffer;
|
||||
template<class buffer, size_t align> struct unique_buffer;
|
||||
|
||||
template<class T> using buffers = std::initializer_list<T>;
|
||||
using const_buffers = buffers<const_buffer>;
|
||||
using mutable_buffers = buffers<mutable_buffer>;
|
||||
|
||||
extern const mutable_buffer null_buffer;
|
||||
extern const mutable_buffers null_buffers;
|
||||
|
||||
template<class it> it rend(const buffer<it> &buffer);
|
||||
template<class it> it end(const buffer<it> &buffer);
|
||||
template<class it> it rbegin(const buffer<it> &buffer);
|
||||
template<class it> it begin(const buffer<it> &buffer);
|
||||
|
||||
template<class it> size_t size(const buffer<it> &buffer);
|
||||
template<class T> size_t size(const buffers<T> &buffers);
|
||||
template<class it> it data(const buffer<it> &buffer);
|
||||
|
||||
template<class it> size_t consume(buffer<it> &buffer, const size_t &bytes);
|
||||
template<class T> size_t consume(buffers<T> &buffers, const size_t &bytes);
|
||||
|
||||
template<class it> char *copy(char *&dest, char *const &stop, const buffer<it> &buffer);
|
||||
template<class it> size_t copy(char *const &dest, const size_t &max, const buffer<it> &buffer);
|
||||
|
||||
template<class T> char *copy(char *&dest, char *const &stop, const buffers<T> &buffer);
|
||||
template<class T> size_t copy(char *const &dest, const size_t &max, const buffers<T> &buffer);
|
||||
|
||||
template<class it> std::ostream &operator<<(std::ostream &s, const buffer<it> &buffer);
|
||||
template<class T> std::ostream &operator<<(std::ostream &s, const buffers<T> &buffers);
|
||||
}
|
||||
|
||||
// Export these important aliases down to main ircd namespace
|
||||
namespace ircd
|
||||
{
|
||||
using buffer::const_buffer;
|
||||
using buffer::mutable_buffer;
|
||||
using buffer::unique_buffer;
|
||||
using buffer::const_buffers;
|
||||
using buffer::mutable_buffers;
|
||||
using buffer::null_buffer;
|
||||
using buffer::null_buffers;
|
||||
}
|
||||
|
||||
template<class it>
|
||||
struct buffer
|
||||
struct ircd::buffer::buffer
|
||||
:std::tuple<it, it>
|
||||
{
|
||||
using value_type = it;
|
||||
|
@ -44,7 +89,7 @@ struct buffer
|
|||
{}
|
||||
};
|
||||
|
||||
struct const_buffer
|
||||
struct ircd::buffer::const_buffer
|
||||
:buffer<const char *>
|
||||
{
|
||||
operator boost::asio::const_buffer() const;
|
||||
|
@ -55,7 +100,7 @@ struct const_buffer
|
|||
{}
|
||||
};
|
||||
|
||||
struct mutable_buffer
|
||||
struct ircd::buffer::mutable_buffer
|
||||
:buffer<char *>
|
||||
{
|
||||
operator boost::asio::mutable_buffer() const;
|
||||
|
@ -65,7 +110,7 @@ struct mutable_buffer
|
|||
|
||||
template<class buffer,
|
||||
size_t align = 16>
|
||||
struct unique_buffer
|
||||
struct ircd::buffer::unique_buffer
|
||||
:buffer
|
||||
{
|
||||
unique_buffer(std::unique_ptr<uint8_t[]> &&, const size_t &size);
|
||||
|
@ -76,53 +121,6 @@ struct unique_buffer
|
|||
~unique_buffer() noexcept;
|
||||
};
|
||||
|
||||
template<class T> using buffers = std::initializer_list<T>;
|
||||
using const_buffers = buffers<const_buffer>;
|
||||
using mutable_buffers = buffers<mutable_buffer>;
|
||||
|
||||
const mutable_buffer null_buffer
|
||||
{
|
||||
nullptr, nullptr
|
||||
};
|
||||
|
||||
const mutable_buffers null_buffers
|
||||
{{
|
||||
null_buffer
|
||||
}};
|
||||
|
||||
template<class it> it rend(const buffer<it> &buffer);
|
||||
template<class it> it end(const buffer<it> &buffer);
|
||||
template<class it> it rbegin(const buffer<it> &buffer);
|
||||
template<class it> it begin(const buffer<it> &buffer);
|
||||
|
||||
template<class it> size_t size(const buffer<it> &buffer);
|
||||
template<class T> size_t size(const buffers<T> &buffers);
|
||||
template<class it> it data(const buffer<it> &buffer);
|
||||
|
||||
template<class it> size_t consume(buffer<it> &buffer, const size_t &bytes);
|
||||
template<class T> size_t consume(buffers<T> &buffers, const size_t &bytes);
|
||||
|
||||
template<class it> char *copy(char *&dest, char *const &stop, const buffer<it> &buffer);
|
||||
template<class it> size_t copy(char *const &dest, const size_t &max, const buffer<it> &buffer);
|
||||
|
||||
template<class T> char *copy(char *&dest, char *const &stop, const buffers<T> &buffer);
|
||||
template<class T> size_t copy(char *const &dest, const size_t &max, const buffers<T> &buffer);
|
||||
|
||||
template<class it> std::ostream &operator<<(std::ostream &s, const buffer<it> &buffer);
|
||||
template<class T> std::ostream &operator<<(std::ostream &s, const buffers<T> &buffers);
|
||||
|
||||
} // namespace buffer
|
||||
|
||||
using buffer::const_buffer;
|
||||
using buffer::mutable_buffer;
|
||||
using buffer::unique_buffer;
|
||||
using buffer::const_buffers;
|
||||
using buffer::mutable_buffers;
|
||||
using buffer::null_buffer;
|
||||
using buffer::null_buffers;
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
template<class T>
|
||||
std::ostream &
|
||||
ircd::buffer::operator<<(std::ostream &s, const buffers<T> &buffers)
|
||||
|
|
|
@ -27,21 +27,30 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CLIENT_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, client_error)
|
||||
IRCD_EXCEPTION(client_error, broken_pipe)
|
||||
IRCD_EXCEPTION(client_error, disconnected)
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, client_error)
|
||||
IRCD_EXCEPTION(client_error, broken_pipe)
|
||||
IRCD_EXCEPTION(client_error, disconnected)
|
||||
struct socket;
|
||||
struct client;
|
||||
|
||||
struct socket;
|
||||
struct client
|
||||
const char *write(client &, const char *&start, const char *const &stop);
|
||||
char *read(client &, char *&start, char *const &stop);
|
||||
string_view readline(client &, char *&start, char *const &stop);
|
||||
http::response::write_closure write_closure(client &);
|
||||
parse::read_closure read_closure(client &);
|
||||
std::shared_ptr<client> add_client(std::shared_ptr<socket>); // Creates a client.
|
||||
}
|
||||
|
||||
struct ircd::client
|
||||
:std::enable_shared_from_this<client>
|
||||
{
|
||||
struct init;
|
||||
|
||||
using list = std::list<client *>;
|
||||
using host_port_pair = std::pair<std::string, uint16_t>;
|
||||
using host_port = IRCD_WEAK_T(host_port_pair);
|
||||
using list = std::list<client *>;
|
||||
|
||||
static list clients;
|
||||
|
||||
|
@ -60,31 +69,20 @@ struct client
|
|||
client &operator=(client &&) = delete;
|
||||
client &operator=(const client &) = delete;
|
||||
virtual ~client() noexcept;
|
||||
|
||||
friend host_port remote_addr(const client &);
|
||||
friend host_port local_addr(const client &);
|
||||
friend std::string string(const host_port &);
|
||||
friend const auto &host(const host_port &);
|
||||
friend const auto &port(const host_port &);
|
||||
};
|
||||
|
||||
struct client::init
|
||||
struct ircd::client::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
client::host_port remote_addr(const client &);
|
||||
client::host_port local_addr(const client &);
|
||||
std::string string(const client::host_port &);
|
||||
const auto &host(const client::host_port &);
|
||||
const auto &port(const client::host_port &);
|
||||
|
||||
const char *write(client &, const char *&start, const char *const &stop);
|
||||
char *read(client &, char *&start, char *const &stop);
|
||||
string_view readline(client &, char *&start, char *const &stop);
|
||||
|
||||
http::response::write_closure write_closure(client &);
|
||||
parse::read_closure read_closure(client &);
|
||||
|
||||
std::shared_ptr<client> add_client(std::shared_ptr<socket>); // Creates a client.
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
inline const auto &
|
||||
ircd::port(const client::host_port &host_port)
|
||||
{
|
||||
|
|
|
@ -20,23 +20,26 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_COLOR_H
|
||||
|
||||
namespace ircd {
|
||||
namespace color {
|
||||
|
||||
enum mode
|
||||
:uint8_t
|
||||
namespace ircd::color
|
||||
{
|
||||
OFF = 0x0f,
|
||||
BOLD = 0x02,
|
||||
COLOR = 0x03,
|
||||
ITALIC = 0x09,
|
||||
STRIKE = 0x13,
|
||||
UNDER = 0x15,
|
||||
UNDER2 = 0x1f,
|
||||
REVERSE = 0x16,
|
||||
};
|
||||
enum mode
|
||||
:uint8_t
|
||||
{
|
||||
OFF = 0x0f,
|
||||
BOLD = 0x02,
|
||||
COLOR = 0x03,
|
||||
ITALIC = 0x09,
|
||||
STRIKE = 0x13,
|
||||
UNDER = 0x15,
|
||||
UNDER2 = 0x1f,
|
||||
REVERSE = 0x16,
|
||||
};
|
||||
|
||||
enum class fg
|
||||
enum class fg;
|
||||
enum class bg;
|
||||
}
|
||||
|
||||
enum class ircd::color::fg
|
||||
{
|
||||
WHITE, BLACK, BLUE, GREEN,
|
||||
LRED, RED, MAGENTA, ORANGE,
|
||||
|
@ -44,13 +47,10 @@ enum class fg
|
|||
LBLUE, LMAGENTA, GRAY, LGRAY
|
||||
};
|
||||
|
||||
enum class bg
|
||||
enum class ircd::color::bg
|
||||
{
|
||||
LGRAY_BLINK, BLACK, BLUE, GREEN,
|
||||
RED_BLINK, RED, MAGENTA, ORANGE,
|
||||
ORANGE_BLINK, GREEN_BLINK, CYAN, CYAN_BLINK,
|
||||
BLUE_BLINK, MAGENTA_BLINK, BLACK_BLINK, LGRAY,
|
||||
};
|
||||
|
||||
} // namespace color
|
||||
} // namespace ircd
|
||||
|
|
|
@ -42,18 +42,15 @@
|
|||
// included when boost/asio.hpp is also included and calls are actually made into boost.
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
using std::chrono::steady_clock;
|
||||
using time_point = steady_clock::time_point;
|
||||
|
||||
using std::chrono::steady_clock;
|
||||
using time_point = steady_clock::time_point;
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, interrupted)
|
||||
IRCD_EXCEPTION(error, timeout)
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, interrupted)
|
||||
IRCD_EXCEPTION(error, timeout)
|
||||
}
|
||||
|
||||
#include "ctx/ctx.h"
|
||||
#include "ctx/context.h"
|
||||
|
@ -68,10 +65,9 @@ IRCD_EXCEPTION(error, timeout)
|
|||
#include "ctx/pool.h"
|
||||
#include "ctx/ole.h"
|
||||
|
||||
namespace ircd {
|
||||
|
||||
using ctx::timeout;
|
||||
using ctx::context;
|
||||
using ctx::sleep;
|
||||
|
||||
} // namespace ircd
|
||||
namespace ircd
|
||||
{
|
||||
using ctx::timeout;
|
||||
using ctx::context;
|
||||
using ctx::sleep;
|
||||
}
|
||||
|
|
|
@ -22,33 +22,41 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_ASYNC_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
|
||||
template<class F,
|
||||
class... A>
|
||||
constexpr bool
|
||||
is_void_result()
|
||||
namespace ircd::ctx
|
||||
{
|
||||
return std::is_void<typename std::result_of<F (A...)>::type>::value;
|
||||
template<class F,
|
||||
class... A>
|
||||
constexpr bool is_void_result();
|
||||
|
||||
template<class F,
|
||||
class... A>
|
||||
using future_void = typename std::enable_if<is_void_result<F, A...>(), future<void>>::type;
|
||||
|
||||
template<class F,
|
||||
class... A>
|
||||
using future_value = typename std::enable_if<!is_void_result<F, A...>(),
|
||||
future<typename std::result_of<F (A...)>::type>>::type;
|
||||
|
||||
template<size_t stack_size = DEFAULT_STACK_SIZE,
|
||||
context::flags flags = (context::flags)0,
|
||||
class F,
|
||||
class... A>
|
||||
future_value<F, A...> async(F&& f, A&&... a);
|
||||
|
||||
template<size_t stack_size = DEFAULT_STACK_SIZE,
|
||||
context::flags flags = context::flags(0),
|
||||
class F,
|
||||
class... A>
|
||||
future_void<F, A...> async(F&& f, A&&... a);
|
||||
}
|
||||
|
||||
template<class F,
|
||||
class... A>
|
||||
using future_void = typename std::enable_if<is_void_result<F, A...>(), future<void>>::type;
|
||||
|
||||
template<class F,
|
||||
class... A>
|
||||
using future_value = typename std::enable_if<!is_void_result<F, A...>(),
|
||||
future<typename std::result_of<F (A...)>::type>>::type;
|
||||
|
||||
template<size_t stack_size = DEFAULT_STACK_SIZE,
|
||||
context::flags flags = (context::flags)0,
|
||||
template<size_t stack_size,
|
||||
ircd::ctx::context::flags flags,
|
||||
class F,
|
||||
class... A>
|
||||
future_value<F, A...>
|
||||
async(F&& f,
|
||||
A&&... a)
|
||||
ircd::ctx::future_value<F, A...>
|
||||
ircd::ctx::async(F&& f,
|
||||
A&&... a)
|
||||
{
|
||||
using R = typename std::result_of<F (A...)>::type;
|
||||
|
||||
|
@ -66,13 +74,13 @@ async(F&& f,
|
|||
return ret;
|
||||
}
|
||||
|
||||
template<size_t stack_size = DEFAULT_STACK_SIZE,
|
||||
context::flags flags = context::flags(0),
|
||||
template<size_t stack_size,
|
||||
ircd::ctx::context::flags flags,
|
||||
class F,
|
||||
class... A>
|
||||
future_void<F, A...>
|
||||
async(F&& f,
|
||||
A&&... a)
|
||||
ircd::ctx::future_void<F, A...>
|
||||
ircd::ctx::async(F&& f,
|
||||
A&&... a)
|
||||
{
|
||||
using R = typename std::result_of<F (A...)>::type;
|
||||
|
||||
|
@ -91,5 +99,10 @@ async(F&& f,
|
|||
return ret;
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
template<class F,
|
||||
class... A>
|
||||
constexpr bool
|
||||
ircd::ctx::is_void_result()
|
||||
{
|
||||
return std::is_void<typename std::result_of<F (A...)>::type>::value;
|
||||
}
|
||||
|
|
|
@ -25,15 +25,17 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_CONTEXT_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
|
||||
const size_t DEFAULT_STACK_SIZE
|
||||
namespace ircd::ctx
|
||||
{
|
||||
64_KiB
|
||||
};
|
||||
struct context;
|
||||
|
||||
struct context
|
||||
const size_t DEFAULT_STACK_SIZE
|
||||
{
|
||||
64_KiB
|
||||
};
|
||||
}
|
||||
|
||||
struct ircd::ctx::context
|
||||
{
|
||||
enum flags
|
||||
{
|
||||
|
@ -94,11 +96,8 @@ struct context
|
|||
};
|
||||
|
||||
inline void
|
||||
swap(context &a, context &b)
|
||||
ircd::ctx::swap(context &a, context &b)
|
||||
noexcept
|
||||
{
|
||||
std::swap(a.c, b.c);
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -24,10 +24,18 @@
|
|||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct continuation;
|
||||
}
|
||||
|
||||
struct continuation
|
||||
namespace ircd
|
||||
{
|
||||
using ctx::continuation;
|
||||
using yield = boost::asio::yield_context;
|
||||
}
|
||||
|
||||
struct ircd::ctx::continuation
|
||||
{
|
||||
ctx *self;
|
||||
|
||||
|
@ -37,10 +45,3 @@ struct continuation
|
|||
continuation(ctx *const &self = ircd::ctx::current);
|
||||
~continuation() noexcept;
|
||||
};
|
||||
|
||||
} // namespace ctx
|
||||
|
||||
using ctx::continuation;
|
||||
using yield = boost::asio::yield_context;
|
||||
|
||||
} // namespace ircd
|
||||
|
|
|
@ -25,57 +25,56 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_CTX_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// low-level ctx interface exposure
|
||||
//
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct ctx;
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
IRCD_OVERLOAD(threadsafe)
|
||||
|
||||
struct ctx;
|
||||
const uint64_t &id(const ctx &); // Unique ID for context
|
||||
string_view name(const ctx &); // User's optional label for context
|
||||
const int64_t ¬es(const ctx &); // Peeks at internal semaphore count
|
||||
bool finished(const ctx &); // Context function returned (or exception).
|
||||
bool started(const ctx &); // Context was ever entered.
|
||||
|
||||
IRCD_OVERLOAD(threadsafe)
|
||||
|
||||
const uint64_t &id(const ctx &); // Unique ID for context
|
||||
string_view name(const ctx &); // User's optional label for context
|
||||
const int64_t ¬es(const ctx &); // Peeks at internal semaphore count (you don't need this)
|
||||
bool finished(const ctx &); // Context function returned (or exception).
|
||||
bool started(const ctx &); // Context was ever entered.
|
||||
|
||||
void interrupt(ctx &); // Interrupt the context for termination.
|
||||
void strand(ctx &, std::function<void ()>); // Post function to context strand
|
||||
void notify(ctx &, threadsafe_t); // Notify context with threadsafety.
|
||||
bool notify(ctx &); // Queue a context switch (only library ppl need this)
|
||||
void yield(ctx &); // Direct context switch (only library ppl need this)
|
||||
void interrupt(ctx &); // Interrupt the context for termination.
|
||||
void strand(ctx &, std::function<void ()>); // Post function to context strand
|
||||
void notify(ctx &, threadsafe_t); // Notify context with threadsafety.
|
||||
bool notify(ctx &); // Queue a context switch
|
||||
void yield(ctx &); // Direct context switch
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// "this_context" interface relevant to the currently running context
|
||||
//
|
||||
namespace ircd::ctx
|
||||
{
|
||||
extern __thread struct ctx *current; // Always set to the currently running context or null
|
||||
|
||||
extern __thread struct ctx *current; // Always set to the currently running context or null
|
||||
ctx &cur(); // Convenience for *current (try to use this instead)
|
||||
void yield(); // Allow other contexts to run before returning.
|
||||
void wait(); // Returns when context notified.
|
||||
|
||||
ctx &cur(); // Convenience for *current (try to use this instead)
|
||||
void yield(); // Allow other contexts to run before returning.
|
||||
void wait(); // Returns when context notified.
|
||||
// Return remaining time if notified; or <= 0 if not, and timeout thrown on throw overloads
|
||||
microseconds wait(const microseconds &, const std::nothrow_t &);
|
||||
template<class E, class duration> nothrow_overload<E, duration> wait(const duration &);
|
||||
template<class E = timeout, class duration> throw_overload<E, duration> wait(const duration &);
|
||||
|
||||
// Return remaining time if notified; or <= 0 if not, and timeout thrown on throw overloads
|
||||
microseconds wait(const microseconds &, const std::nothrow_t &);
|
||||
template<class E, class duration> nothrow_overload<E, duration> wait(const duration &);
|
||||
template<class E = timeout, class duration> throw_overload<E, duration> wait(const duration &);
|
||||
// Returns false if notified; true if time point reached, timeout thrown on throw_overloads
|
||||
bool wait_until(const time_point &tp, const std::nothrow_t &);
|
||||
template<class E> nothrow_overload<E, bool> wait_until(const time_point &tp);
|
||||
template<class E = timeout> throw_overload<E> wait_until(const time_point &tp);
|
||||
|
||||
// Returns false if notified; true if time point reached, timeout thrown on throw_overloads
|
||||
bool wait_until(const time_point &tp, const std::nothrow_t &);
|
||||
template<class E> nothrow_overload<E, bool> wait_until(const time_point &tp);
|
||||
template<class E = timeout> throw_overload<E> wait_until(const time_point &tp);
|
||||
|
||||
// Ignores notes. Throws if interrupted.
|
||||
void sleep_until(const time_point &tp);
|
||||
template<class duration> void sleep(const duration &);
|
||||
void sleep(const int &secs);
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
// Ignores notes. Throws if interrupted.
|
||||
void sleep_until(const time_point &tp);
|
||||
template<class duration> void sleep(const duration &);
|
||||
void sleep(const int &secs);
|
||||
}
|
||||
|
||||
inline void
|
||||
ircd::ctx::sleep(const int &secs)
|
||||
|
|
|
@ -22,19 +22,18 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_DOCK_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
|
||||
enum class cv_status
|
||||
namespace ircd::ctx
|
||||
{
|
||||
no_timeout, timeout
|
||||
};
|
||||
struct dock;
|
||||
enum class cv_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* a dock is a condition variable which has no requirement for locking
|
||||
* because the context system does not require mutual exclusion.
|
||||
*/
|
||||
class dock
|
||||
//
|
||||
// a dock is a condition variable which has no requirement for locking because
|
||||
// the context system does not require mutual exclusion for coherence, however
|
||||
// we have to create our own queue here rather than piggyback a mutex's.
|
||||
//
|
||||
class ircd::ctx::dock
|
||||
{
|
||||
std::deque<ctx *> q;
|
||||
|
||||
|
@ -61,15 +60,20 @@ class dock
|
|||
~dock() noexcept;
|
||||
};
|
||||
|
||||
enum class ircd::ctx::cv_status
|
||||
{
|
||||
no_timeout, timeout
|
||||
};
|
||||
|
||||
inline
|
||||
dock::~dock()
|
||||
ircd::ctx::dock::~dock()
|
||||
noexcept
|
||||
{
|
||||
assert(q.empty());
|
||||
}
|
||||
|
||||
inline void
|
||||
dock::notify()
|
||||
ircd::ctx::dock::notify()
|
||||
noexcept
|
||||
{
|
||||
if(q.empty())
|
||||
|
@ -82,7 +86,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
dock::notify_one()
|
||||
ircd::ctx::dock::notify_one()
|
||||
noexcept
|
||||
{
|
||||
if(q.empty())
|
||||
|
@ -92,7 +96,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
dock::notify_all()
|
||||
ircd::ctx::dock::notify_all()
|
||||
noexcept
|
||||
{
|
||||
// We copy the queue and post all notifications without requesting direct context switches.
|
||||
|
@ -105,7 +109,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
dock::wait()
|
||||
ircd::ctx::dock::wait()
|
||||
{
|
||||
const scope remove(std::bind(&dock::remove_self, this));
|
||||
q.emplace_back(&cur());
|
||||
|
@ -114,7 +118,7 @@ dock::wait()
|
|||
|
||||
template<class predicate>
|
||||
void
|
||||
dock::wait(predicate&& pred)
|
||||
ircd::ctx::dock::wait(predicate&& pred)
|
||||
{
|
||||
if(pred())
|
||||
return;
|
||||
|
@ -128,8 +132,8 @@ dock::wait(predicate&& pred)
|
|||
}
|
||||
|
||||
template<class duration>
|
||||
cv_status
|
||||
dock::wait_for(const duration &dur)
|
||||
ircd::ctx::cv_status
|
||||
ircd::ctx::dock::wait_for(const duration &dur)
|
||||
{
|
||||
static const duration zero(0);
|
||||
|
||||
|
@ -143,7 +147,7 @@ dock::wait_for(const duration &dur)
|
|||
template<class duration,
|
||||
class predicate>
|
||||
bool
|
||||
dock::wait_for(const duration &dur,
|
||||
ircd::ctx::dock::wait_for(const duration &dur,
|
||||
predicate&& pred)
|
||||
{
|
||||
static const duration zero(0);
|
||||
|
@ -166,8 +170,8 @@ dock::wait_for(const duration &dur,
|
|||
}
|
||||
|
||||
template<class time_point>
|
||||
cv_status
|
||||
dock::wait_until(time_point&& tp)
|
||||
ircd::ctx::cv_status
|
||||
ircd::ctx::dock::wait_until(time_point&& tp)
|
||||
{
|
||||
const scope remove(std::bind(&dock::remove_self, this));
|
||||
q.emplace_back(&cur());
|
||||
|
@ -179,7 +183,7 @@ dock::wait_until(time_point&& tp)
|
|||
template<class time_point,
|
||||
class predicate>
|
||||
bool
|
||||
dock::wait_until(time_point&& tp,
|
||||
ircd::ctx::dock::wait_until(time_point&& tp,
|
||||
predicate&& pred)
|
||||
{
|
||||
if(pred())
|
||||
|
@ -200,7 +204,7 @@ dock::wait_until(time_point&& tp,
|
|||
}
|
||||
|
||||
inline void
|
||||
dock::notify(ctx &ctx)
|
||||
ircd::ctx::dock::notify(ctx &ctx)
|
||||
noexcept
|
||||
{
|
||||
// This branch handles dock.notify() being called from outside the context system.
|
||||
|
@ -214,12 +218,9 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
dock::remove_self()
|
||||
ircd::ctx::dock::remove_self()
|
||||
{
|
||||
const auto it(std::find(begin(q), end(q), &cur()));
|
||||
assert(it != end(q));
|
||||
q.erase(it);
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,18 +22,28 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_FUTURE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
template<class T = void> class future;
|
||||
template<> class future<void>;
|
||||
template<class... T> struct scoped_future;
|
||||
|
||||
enum class future_status
|
||||
enum class future_status;
|
||||
|
||||
template<class T,
|
||||
class time_point>
|
||||
future_status wait_until(const future<T> &, const time_point &);
|
||||
}
|
||||
|
||||
enum class ircd::ctx::future_status
|
||||
{
|
||||
ready,
|
||||
timeout,
|
||||
deferred,
|
||||
};
|
||||
|
||||
template<class T = void>
|
||||
class future
|
||||
template<class T>
|
||||
class ircd::ctx::future
|
||||
{
|
||||
std::shared_ptr<shared_state<T>> st;
|
||||
|
||||
|
@ -59,7 +69,7 @@ class future
|
|||
};
|
||||
|
||||
template<>
|
||||
class future<void>
|
||||
class ircd::ctx::future<void>
|
||||
{
|
||||
std::shared_ptr<shared_state<void>> st;
|
||||
|
||||
|
@ -79,12 +89,9 @@ class future<void>
|
|||
future(promise<void> &promise);
|
||||
};
|
||||
|
||||
template<class T,
|
||||
class time_point>
|
||||
future_status wait_until(const future<T> &, const time_point &);
|
||||
|
||||
template<class... T>
|
||||
struct scoped_future : future<T...>
|
||||
struct ircd::ctx::scoped_future
|
||||
:future<T...>
|
||||
{
|
||||
template<class... Args> scoped_future(Args&&... args);
|
||||
~scoped_future() noexcept;
|
||||
|
@ -92,13 +99,13 @@ struct scoped_future : future<T...>
|
|||
|
||||
template<class... T>
|
||||
template<class... Args>
|
||||
scoped_future<T...>::scoped_future(Args&&... args):
|
||||
future<T...>{std::forward<Args>(args)...}
|
||||
ircd::ctx::scoped_future<T...>::scoped_future(Args&&... args)
|
||||
:future<T...>{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
|
||||
template<class... T>
|
||||
scoped_future<T...>::~scoped_future()
|
||||
ircd::ctx::scoped_future<T...>::~scoped_future()
|
||||
noexcept
|
||||
{
|
||||
if(std::uncaught_exception())
|
||||
|
@ -109,32 +116,32 @@ noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
future<void>::future():
|
||||
ircd::ctx::future<void>::future():
|
||||
st(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
future<T>::future():
|
||||
ircd::ctx::future<T>::future():
|
||||
st(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
future<void>::future(promise<void> &promise):
|
||||
ircd::ctx::future<void>::future(promise<void> &promise):
|
||||
st(promise.get_state().share())
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
future<T>::future(promise<T> &promise):
|
||||
ircd::ctx::future<T>::future(promise<T> &promise):
|
||||
st(promise.get_state().share())
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
future<T>::get()
|
||||
ircd::ctx::future<T>::get()
|
||||
{
|
||||
wait();
|
||||
|
||||
|
@ -145,7 +152,7 @@ future<T>::get()
|
|||
}
|
||||
|
||||
inline void
|
||||
future<void>::wait()
|
||||
ircd::ctx::future<void>::wait()
|
||||
const
|
||||
{
|
||||
this->wait_until(steady_clock::time_point::max());
|
||||
|
@ -153,15 +160,15 @@ const
|
|||
|
||||
template<class T>
|
||||
void
|
||||
future<T>::wait()
|
||||
ircd::ctx::future<T>::wait()
|
||||
const
|
||||
{
|
||||
this->wait_until(steady_clock::time_point::max());
|
||||
}
|
||||
|
||||
template<class duration>
|
||||
future_status
|
||||
future<void>::wait(const duration &d)
|
||||
ircd::ctx::future_status
|
||||
ircd::ctx::future<void>::wait(const duration &d)
|
||||
const
|
||||
{
|
||||
return this->wait_until(steady_clock::now() + d);
|
||||
|
@ -169,8 +176,8 @@ const
|
|||
|
||||
template<class T>
|
||||
template<class duration>
|
||||
future_status
|
||||
future<T>::wait(const duration &d)
|
||||
ircd::ctx::future_status
|
||||
ircd::ctx::future<T>::wait(const duration &d)
|
||||
const
|
||||
{
|
||||
return this->wait_until(steady_clock::now() + d);
|
||||
|
@ -178,16 +185,16 @@ const
|
|||
|
||||
template<class T>
|
||||
template<class time_point>
|
||||
future_status
|
||||
future<T>::wait_until(const time_point &tp)
|
||||
ircd::ctx::future_status
|
||||
ircd::ctx::future<T>::wait_until(const time_point &tp)
|
||||
const
|
||||
{
|
||||
return ircd::ctx::wait_until(*this, tp);
|
||||
}
|
||||
|
||||
template<class time_point>
|
||||
future_status
|
||||
future<void>::wait_until(const time_point &tp)
|
||||
ircd::ctx::future_status
|
||||
ircd::ctx::future<void>::wait_until(const time_point &tp)
|
||||
const
|
||||
{
|
||||
return ircd::ctx::wait_until(*this, tp);
|
||||
|
@ -195,9 +202,9 @@ const
|
|||
|
||||
template<class T,
|
||||
class time_point>
|
||||
future_status
|
||||
wait_until(const future<T> &f,
|
||||
const time_point &tp)
|
||||
ircd::ctx::future_status
|
||||
ircd::ctx::wait_until(const future<T> &f,
|
||||
const time_point &tp)
|
||||
{
|
||||
const auto wfun([&f]() -> bool
|
||||
{
|
||||
|
@ -213,6 +220,3 @@ wait_until(const future<T> &f,
|
|||
return likely(wfun())? future_status::ready:
|
||||
future_status::deferred;
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,15 +22,17 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_MUTEX_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
class mutex;
|
||||
}
|
||||
|
||||
/**
|
||||
* The mutex only allows one context to lock it and continue,
|
||||
* additional contexts are queued. This can be used with std::
|
||||
* locking concepts.
|
||||
*/
|
||||
class mutex
|
||||
//
|
||||
// The mutex only allows one context to lock it and continue,
|
||||
// additional contexts are queued. This can be used with std::
|
||||
// locking concepts.
|
||||
//
|
||||
class ircd::ctx::mutex
|
||||
{
|
||||
bool m;
|
||||
std::deque<ctx *> q;
|
||||
|
@ -48,13 +50,13 @@ class mutex
|
|||
};
|
||||
|
||||
inline
|
||||
mutex::mutex():
|
||||
ircd::ctx::mutex::mutex():
|
||||
m(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
mutex::~mutex()
|
||||
ircd::ctx::mutex::~mutex()
|
||||
noexcept
|
||||
{
|
||||
assert(!m);
|
||||
|
@ -62,7 +64,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
mutex::unlock()
|
||||
ircd::ctx::mutex::unlock()
|
||||
{
|
||||
ctx *next; do
|
||||
{
|
||||
|
@ -82,7 +84,7 @@ mutex::unlock()
|
|||
}
|
||||
|
||||
inline void
|
||||
mutex::lock()
|
||||
ircd::ctx::mutex::lock()
|
||||
{
|
||||
if(likely(try_lock()))
|
||||
return;
|
||||
|
@ -94,14 +96,14 @@ mutex::lock()
|
|||
|
||||
template<class duration>
|
||||
bool
|
||||
mutex::try_lock_for(const duration &d)
|
||||
ircd::ctx::mutex::try_lock_for(const duration &d)
|
||||
{
|
||||
return try_lock_until(steady_clock::now() + d);
|
||||
}
|
||||
|
||||
template<class time_point>
|
||||
bool
|
||||
mutex::try_lock_until(const time_point &tp)
|
||||
ircd::ctx::mutex::try_lock_until(const time_point &tp)
|
||||
{
|
||||
if(likely(try_lock()))
|
||||
return true;
|
||||
|
@ -122,7 +124,7 @@ mutex::try_lock_until(const time_point &tp)
|
|||
}
|
||||
|
||||
inline bool
|
||||
mutex::try_lock()
|
||||
ircd::ctx::mutex::try_lock()
|
||||
{
|
||||
if(m)
|
||||
return false;
|
||||
|
@ -130,6 +132,3 @@ mutex::try_lock()
|
|||
m = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -46,21 +46,20 @@
|
|||
// to make a good case for an offload that doesn't hurt more than it helps. And when it hurts,
|
||||
// it hurts _everything_.
|
||||
//
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ole {
|
||||
namespace ircd::ctx::ole
|
||||
{
|
||||
struct init;
|
||||
|
||||
void offload(const std::function<void ()> &);
|
||||
void offload(const std::function<void ()> &);
|
||||
}
|
||||
|
||||
struct init
|
||||
namespace ircd::ctx
|
||||
{
|
||||
using ole::offload;
|
||||
}
|
||||
|
||||
struct ircd::ctx::ole::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
} // namespace ole
|
||||
|
||||
using ole::offload;
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_POOL_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct pool;
|
||||
}
|
||||
|
||||
struct pool
|
||||
struct ircd::ctx::pool
|
||||
{
|
||||
using closure = std::function<void ()>;
|
||||
|
||||
|
@ -71,9 +73,9 @@ struct pool
|
|||
|
||||
template<class F,
|
||||
class... A>
|
||||
future_value<F, A...>
|
||||
pool::async(F&& f,
|
||||
A&&... a)
|
||||
ircd::ctx::future_value<F, A...>
|
||||
ircd::ctx::pool::async(F&& f,
|
||||
A&&... a)
|
||||
{
|
||||
using R = typename std::result_of<F (A...)>::type;
|
||||
|
||||
|
@ -90,9 +92,9 @@ pool::async(F&& f,
|
|||
|
||||
template<class F,
|
||||
class... A>
|
||||
future_void<F, A...>
|
||||
pool::async(F&& f,
|
||||
A&&... a)
|
||||
ircd::ctx::future_void<F, A...>
|
||||
ircd::ctx::pool::async(F&& f,
|
||||
A&&... a)
|
||||
{
|
||||
using R = typename std::result_of<F (A...)>::type;
|
||||
|
||||
|
@ -107,6 +109,3 @@ pool::async(F&& f,
|
|||
|
||||
return future<R>(*p);
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -36,22 +36,15 @@
|
|||
* call which has been passed over for mitigation may start doing some blocking flush under load,
|
||||
* etc. The profiler will alert us of this so it doesn't silently degrade performance.
|
||||
*/
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace prof {
|
||||
|
||||
struct settings
|
||||
namespace ircd::ctx::prof
|
||||
{
|
||||
double stack_usage_warning; // percentage
|
||||
double stack_usage_assertion; // percentage
|
||||
enum class event;
|
||||
struct settings extern settings;
|
||||
|
||||
microseconds slice_warning; // Warn when the yield-to-yield time exceeds
|
||||
microseconds slice_interrupt; // Interrupt exception when exceeded (not a signal)
|
||||
microseconds slice_assertion; // abort() when exceeded (not a signal, must yield)
|
||||
void mark(const event &);
|
||||
}
|
||||
extern settings;
|
||||
|
||||
enum class event
|
||||
enum class ircd::ctx::prof::event
|
||||
{
|
||||
SPAWN, // Context spawn requested
|
||||
JOIN, // Context join requested
|
||||
|
@ -63,8 +56,12 @@ enum class event
|
|||
CUR_INTERRUPT, // Current context detects interruption
|
||||
};
|
||||
|
||||
void mark(const event &);
|
||||
struct ircd::ctx::prof::settings
|
||||
{
|
||||
double stack_usage_warning; // percentage
|
||||
double stack_usage_assertion; // percentage
|
||||
|
||||
} // namespace prof
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
microseconds slice_warning; // Warn when the yield-to-yield time exceeds
|
||||
microseconds slice_interrupt; // Interrupt exception when exceeded (not a signal)
|
||||
microseconds slice_assertion; // abort() when exceeded (not a signal, must yield)
|
||||
};
|
||||
|
|
|
@ -22,17 +22,20 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_PROMISE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::ctx::error, future_error)
|
||||
IRCD_EXCEPTION(future_error, no_state)
|
||||
IRCD_EXCEPTION(future_error, broken_promise)
|
||||
IRCD_EXCEPTION(future_error, future_already_retrieved)
|
||||
IRCD_EXCEPTION(future_error, promise_already_satisfied)
|
||||
|
||||
IRCD_EXCEPTION(ircd::ctx::error, future_error)
|
||||
IRCD_EXCEPTION(future_error, no_state)
|
||||
IRCD_EXCEPTION(future_error, broken_promise)
|
||||
IRCD_EXCEPTION(future_error, future_already_retrieved)
|
||||
IRCD_EXCEPTION(future_error, promise_already_satisfied)
|
||||
template<class T = void> class promise;
|
||||
template<> class promise<void>;
|
||||
}
|
||||
|
||||
template<class T = void>
|
||||
class promise
|
||||
template<class T>
|
||||
class ircd::ctx::promise
|
||||
{
|
||||
std::shared_ptr<shared_state<T>> st;
|
||||
|
||||
|
@ -62,7 +65,7 @@ class promise
|
|||
};
|
||||
|
||||
template<>
|
||||
class promise<void>
|
||||
class ircd::ctx::promise<void>
|
||||
{
|
||||
std::shared_ptr<shared_state<void>> st;
|
||||
|
||||
|
@ -86,29 +89,28 @@ class promise<void>
|
|||
~promise() noexcept;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
promise<void>::promise():
|
||||
ircd::ctx::promise<void>::promise():
|
||||
st(std::make_shared<shared_state<void>>())
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
promise<T>::promise():
|
||||
ircd::ctx::promise<T>::promise():
|
||||
st(std::make_shared<shared_state<T>>())
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
promise<T>::promise(promise<T> &&o)
|
||||
ircd::ctx::promise<T>::promise(promise<T> &&o)
|
||||
noexcept:
|
||||
st(std::move(o.st))
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
promise<T> &
|
||||
promise<T>::operator=(promise<T> &&o)
|
||||
ircd::ctx::promise<T> &
|
||||
ircd::ctx::promise<T>::operator=(promise<T> &&o)
|
||||
noexcept
|
||||
{
|
||||
st = std::move(o.st);
|
||||
|
@ -116,7 +118,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
promise<void>::~promise()
|
||||
ircd::ctx::promise<void>::~promise()
|
||||
noexcept
|
||||
{
|
||||
if(valid() && !st->finished && !st.unique())
|
||||
|
@ -124,7 +126,7 @@ noexcept
|
|||
}
|
||||
|
||||
template<class T>
|
||||
promise<T>::~promise()
|
||||
ircd::ctx::promise<T>::~promise()
|
||||
noexcept
|
||||
{
|
||||
if(valid() && !st->finished && !st.unique())
|
||||
|
@ -132,7 +134,7 @@ noexcept
|
|||
}
|
||||
|
||||
inline void
|
||||
promise<void>::reset()
|
||||
ircd::ctx::promise<void>::reset()
|
||||
{
|
||||
if(valid())
|
||||
st->reset();
|
||||
|
@ -140,7 +142,7 @@ promise<void>::reset()
|
|||
|
||||
template<class T>
|
||||
void
|
||||
promise<T>::reset()
|
||||
ircd::ctx::promise<T>::reset()
|
||||
{
|
||||
if(valid())
|
||||
st->reset();
|
||||
|
@ -148,7 +150,7 @@ promise<T>::reset()
|
|||
|
||||
template<class T>
|
||||
void
|
||||
promise<T>::set_value(T&& val)
|
||||
ircd::ctx::promise<T>::set_value(T&& val)
|
||||
{
|
||||
st->val = std::move(val);
|
||||
st->finished = true;
|
||||
|
@ -156,7 +158,7 @@ promise<T>::set_value(T&& val)
|
|||
}
|
||||
|
||||
inline void
|
||||
promise<void>::set_value()
|
||||
ircd::ctx::promise<void>::set_value()
|
||||
{
|
||||
st->finished = true;
|
||||
st->cond.notify_all();
|
||||
|
@ -164,7 +166,7 @@ promise<void>::set_value()
|
|||
|
||||
template<class T>
|
||||
void
|
||||
promise<T>::set_value(const T &val)
|
||||
ircd::ctx::promise<T>::set_value(const T &val)
|
||||
{
|
||||
st->val = val;
|
||||
st->finished = true;
|
||||
|
@ -172,7 +174,7 @@ promise<T>::set_value(const T &val)
|
|||
}
|
||||
|
||||
inline void
|
||||
promise<void>::set_exception(std::exception_ptr eptr)
|
||||
ircd::ctx::promise<void>::set_exception(std::exception_ptr eptr)
|
||||
{
|
||||
st->eptr = std::move(eptr);
|
||||
st->finished = true;
|
||||
|
@ -181,12 +183,9 @@ promise<void>::set_exception(std::exception_ptr eptr)
|
|||
|
||||
template<class T>
|
||||
void
|
||||
promise<T>::set_exception(std::exception_ptr eptr)
|
||||
ircd::ctx::promise<T>::set_exception(std::exception_ptr eptr)
|
||||
{
|
||||
st->eptr = std::move(eptr);
|
||||
st->finished = true;
|
||||
st->cond.notify_all();
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_QUEUE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
template<class T> class queue;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class queue
|
||||
class ircd::ctx::queue
|
||||
{
|
||||
struct dock dock;
|
||||
std::queue<T> q;
|
||||
|
@ -50,7 +52,7 @@ class queue
|
|||
};
|
||||
|
||||
template<class T>
|
||||
queue<T>::~queue()
|
||||
ircd::ctx::queue<T>::~queue()
|
||||
noexcept
|
||||
{
|
||||
assert(q.empty());
|
||||
|
@ -58,7 +60,7 @@ noexcept
|
|||
|
||||
template<class T>
|
||||
void
|
||||
queue<T>::push(T &&t)
|
||||
ircd::ctx::queue<T>::push(T &&t)
|
||||
noexcept
|
||||
{
|
||||
q.push(std::move(t));
|
||||
|
@ -67,7 +69,7 @@ noexcept
|
|||
|
||||
template<class T>
|
||||
void
|
||||
queue<T>::push(const T &t)
|
||||
ircd::ctx::queue<T>::push(const T &t)
|
||||
{
|
||||
q.push(t);
|
||||
dock.notify();
|
||||
|
@ -76,7 +78,7 @@ queue<T>::push(const T &t)
|
|||
template<class T>
|
||||
template<class... args>
|
||||
void
|
||||
queue<T>::emplace(args&&... a)
|
||||
ircd::ctx::queue<T>::emplace(args&&... a)
|
||||
{
|
||||
q.emplace(std::forward<args>(a)...);
|
||||
dock.notify();
|
||||
|
@ -84,7 +86,7 @@ queue<T>::emplace(args&&... a)
|
|||
|
||||
template<class T>
|
||||
T
|
||||
queue<T>::pop()
|
||||
ircd::ctx::queue<T>::pop()
|
||||
{
|
||||
dock.wait([this]
|
||||
{
|
||||
|
@ -103,7 +105,7 @@ queue<T>::pop()
|
|||
template<class T>
|
||||
template<class duration>
|
||||
T
|
||||
queue<T>::pop_for(const duration &dur)
|
||||
ircd::ctx::queue<T>::pop_for(const duration &dur)
|
||||
{
|
||||
const auto status(dock.wait_for(dur, [this]
|
||||
{
|
||||
|
@ -125,7 +127,7 @@ queue<T>::pop_for(const duration &dur)
|
|||
template<class T>
|
||||
template<class time_point>
|
||||
T
|
||||
queue<T>::pop_until(time_point&& tp)
|
||||
ircd::ctx::queue<T>::pop_until(time_point&& tp)
|
||||
{
|
||||
const auto status(dock.wait_until(tp, [this]
|
||||
{
|
||||
|
@ -143,6 +145,3 @@ queue<T>::pop_until(time_point&& tp)
|
|||
auto &ret(q.front());
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,10 +22,14 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_SHARED_STATE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct shared_state_base;
|
||||
template<class T = void> struct shared_state;
|
||||
template<> struct shared_state<void>;
|
||||
}
|
||||
|
||||
struct shared_state_base
|
||||
struct ircd::ctx::shared_state_base
|
||||
{
|
||||
dock cond;
|
||||
std::exception_ptr eptr;
|
||||
|
@ -34,8 +38,8 @@ struct shared_state_base
|
|||
void reset();
|
||||
};
|
||||
|
||||
template<class T = void>
|
||||
struct shared_state
|
||||
template<class T>
|
||||
struct ircd::ctx::shared_state
|
||||
:shared_state_base
|
||||
,std::enable_shared_from_this<shared_state<T>>
|
||||
{
|
||||
|
@ -50,7 +54,7 @@ struct shared_state
|
|||
};
|
||||
|
||||
template<>
|
||||
struct shared_state<void>
|
||||
struct ircd::ctx::shared_state<void>
|
||||
:shared_state_base
|
||||
,std::enable_shared_from_this<shared_state<void>>
|
||||
{
|
||||
|
@ -60,41 +64,37 @@ struct shared_state<void>
|
|||
std::shared_ptr<shared_state<void>> share();
|
||||
};
|
||||
|
||||
|
||||
inline std::shared_ptr<shared_state<void>>
|
||||
shared_state<void>::share()
|
||||
inline std::shared_ptr<ircd::ctx::shared_state<void>>
|
||||
ircd::ctx::shared_state<void>::share()
|
||||
{
|
||||
return this->shared_from_this();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::shared_ptr<shared_state<T>>
|
||||
shared_state<T>::share()
|
||||
std::shared_ptr<ircd::ctx::shared_state<T>>
|
||||
ircd::ctx::shared_state<T>::share()
|
||||
{
|
||||
return this->shared_from_this();
|
||||
}
|
||||
|
||||
inline std::shared_ptr<const shared_state<void>>
|
||||
shared_state<void>::share()
|
||||
inline std::shared_ptr<const ircd::ctx::shared_state<void>>
|
||||
ircd::ctx::shared_state<void>::share()
|
||||
const
|
||||
{
|
||||
return this->shared_from_this();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::shared_ptr<const shared_state<T>>
|
||||
shared_state<T>::share()
|
||||
std::shared_ptr<const ircd::ctx::shared_state<T>>
|
||||
ircd::ctx::shared_state<T>::share()
|
||||
const
|
||||
{
|
||||
return this->shared_from_this();
|
||||
}
|
||||
|
||||
inline void
|
||||
shared_state_base::reset()
|
||||
ircd::ctx::shared_state_base::reset()
|
||||
{
|
||||
eptr = nullptr;
|
||||
finished = false;
|
||||
}
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
|
|
@ -27,39 +27,37 @@
|
|||
//
|
||||
// Please see db/README.md for documentation.
|
||||
//
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
struct init;
|
||||
struct cell;
|
||||
struct row;
|
||||
struct column;
|
||||
struct database;
|
||||
|
||||
struct cell;
|
||||
struct row;
|
||||
struct column;
|
||||
struct database;
|
||||
// Errors for the database subsystem. The exceptions that use _HIDENAME
|
||||
// are built from RocksDB errors which already have an info string with
|
||||
// an included name.
|
||||
//
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, not_found)
|
||||
IRCD_EXCEPTION(error, schema_error)
|
||||
IRCD_EXCEPTION_HIDENAME(error, corruption)
|
||||
IRCD_EXCEPTION_HIDENAME(error, not_supported)
|
||||
IRCD_EXCEPTION_HIDENAME(error, invalid_argument)
|
||||
IRCD_EXCEPTION_HIDENAME(error, io_error)
|
||||
IRCD_EXCEPTION_HIDENAME(error, merge_in_progress)
|
||||
IRCD_EXCEPTION_HIDENAME(error, incomplete)
|
||||
IRCD_EXCEPTION_HIDENAME(error, shutdown_in_progress)
|
||||
IRCD_EXCEPTION_HIDENAME(error, timed_out)
|
||||
IRCD_EXCEPTION_HIDENAME(error, aborted)
|
||||
IRCD_EXCEPTION_HIDENAME(error, busy)
|
||||
IRCD_EXCEPTION_HIDENAME(error, expired)
|
||||
IRCD_EXCEPTION_HIDENAME(error, try_again)
|
||||
|
||||
// Errors for the database subsystem. The exceptions that use _HIDENAME
|
||||
// are built from RocksDB errors which already have an info string with
|
||||
// an included name.
|
||||
//
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, not_found)
|
||||
IRCD_EXCEPTION(error, schema_error)
|
||||
IRCD_EXCEPTION_HIDENAME(error, corruption)
|
||||
IRCD_EXCEPTION_HIDENAME(error, not_supported)
|
||||
IRCD_EXCEPTION_HIDENAME(error, invalid_argument)
|
||||
IRCD_EXCEPTION_HIDENAME(error, io_error)
|
||||
IRCD_EXCEPTION_HIDENAME(error, merge_in_progress)
|
||||
IRCD_EXCEPTION_HIDENAME(error, incomplete)
|
||||
IRCD_EXCEPTION_HIDENAME(error, shutdown_in_progress)
|
||||
IRCD_EXCEPTION_HIDENAME(error, timed_out)
|
||||
IRCD_EXCEPTION_HIDENAME(error, aborted)
|
||||
IRCD_EXCEPTION_HIDENAME(error, busy)
|
||||
IRCD_EXCEPTION_HIDENAME(error, expired)
|
||||
IRCD_EXCEPTION_HIDENAME(error, try_again)
|
||||
|
||||
// db subsystem has its own logging facility
|
||||
extern struct log::log log;
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
// db subsystem has its own logging facility
|
||||
extern struct log::log log;
|
||||
}
|
||||
|
||||
//
|
||||
// These are forward declarations to objects we may carry a pointer to.
|
||||
|
@ -83,25 +81,22 @@ namespace rocksdb
|
|||
//
|
||||
// Misc utils
|
||||
//
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
extern const char *const version;
|
||||
|
||||
extern const char *const version;
|
||||
rocksdb::Slice slice(const string_view &);
|
||||
string_view slice(const rocksdb::Slice &);
|
||||
|
||||
rocksdb::Slice slice(const string_view &);
|
||||
string_view slice(const rocksdb::Slice &);
|
||||
bool valid(const rocksdb::Iterator &);
|
||||
string_view key(const rocksdb::Iterator &);
|
||||
string_view val(const rocksdb::Iterator &);
|
||||
|
||||
bool valid(const rocksdb::Iterator &);
|
||||
string_view key(const rocksdb::Iterator &);
|
||||
string_view val(const rocksdb::Iterator &);
|
||||
std::string path(const std::string &name);
|
||||
std::vector<std::string> available();
|
||||
|
||||
std::string path(const std::string &name);
|
||||
std::vector<std::string> available();
|
||||
|
||||
void log_rdb_perf_context(const bool &all = true);
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
void log_rdb_perf_context(const bool &all = true);
|
||||
}
|
||||
|
||||
#include "db/delta.h"
|
||||
#include "db/database.h"
|
||||
|
@ -109,24 +104,20 @@ void log_rdb_perf_context(const bool &all = true);
|
|||
#include "db/column.h"
|
||||
#include "db/cell.h"
|
||||
#include "db/row.h"
|
||||
#include "db/object.h"
|
||||
#include "db/value.h"
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
std::string merge_operator(const string_view &, const std::pair<string_view, string_view> &);
|
||||
}
|
||||
|
||||
std::string merge_operator(const string_view &, const std::pair<string_view, string_view> &);
|
||||
namespace ircd
|
||||
{
|
||||
using db::database;
|
||||
}
|
||||
|
||||
struct init
|
||||
struct ircd::db::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
||||
namespace ircd {
|
||||
|
||||
using database = db::database;
|
||||
|
||||
} // namespace ircd
|
||||
|
|
|
@ -23,8 +23,14 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_CELL_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
struct cell;
|
||||
|
||||
// Util
|
||||
const std::string &name(const cell &);
|
||||
uint64_t sequence(const cell &);
|
||||
}
|
||||
|
||||
// A cell is a single key-value element existing within a column. This structure
|
||||
// provides the necessary facilities for working with a single cell. Many simple
|
||||
|
@ -42,7 +48,7 @@ namespace db {
|
|||
// both a normal string and binary data, so this class is not a template and offers
|
||||
// no conversions at this level. see: value.h/object.h
|
||||
//
|
||||
struct cell
|
||||
struct ircd::db::cell
|
||||
{
|
||||
struct delta;
|
||||
|
||||
|
@ -100,12 +106,24 @@ struct cell
|
|||
friend std::ostream &operator<<(std::ostream &s, const cell &c);
|
||||
};
|
||||
|
||||
namespace ircd::db
|
||||
{
|
||||
// [SET] Perform operations in a sequence as a single transaction. No template
|
||||
// iterators supported yet, just a ptr range good for contiguous sequences like
|
||||
// vectors and initializer_lists. To support any iterator I think we'll need to
|
||||
// forward-expose a wrapping of rocksdb::WriteBatch.
|
||||
void write(const cell::delta *const &begin, const cell::delta *const &end, const sopts & = {});
|
||||
void write(const std::initializer_list<cell::delta> &, const sopts & = {});
|
||||
void write(const sopts &, const std::initializer_list<cell::delta> &);
|
||||
void write(const cell::delta &, const sopts & = {});
|
||||
}
|
||||
|
||||
//
|
||||
// A delta is an element of a database transaction. You can use this to change
|
||||
// the values of cells. Use cell deltas to make an all-succeed-or-all-fail
|
||||
// transaction across many cells in various columns at once.
|
||||
//
|
||||
struct cell::delta
|
||||
struct ircd::db::cell::delta
|
||||
:std::tuple<op, cell &, string_view>
|
||||
{
|
||||
delta(cell &c, const string_view &val, const enum op &op = op::SET)
|
||||
|
@ -117,22 +135,6 @@ struct cell::delta
|
|||
{}
|
||||
};
|
||||
|
||||
// [SET] Perform operations in a sequence as a single transaction. No template
|
||||
// iterators supported yet, just a ptr range good for contiguous sequences like
|
||||
// vectors and initializer_lists. To support any iterator I think we'll need to
|
||||
// forward-expose a wrapping of rocksdb::WriteBatch.
|
||||
void write(const cell::delta *const &begin, const cell::delta *const &end, const sopts & = {});
|
||||
void write(const std::initializer_list<cell::delta> &, const sopts & = {});
|
||||
void write(const sopts &, const std::initializer_list<cell::delta> &);
|
||||
void write(const cell::delta &, const sopts & = {});
|
||||
|
||||
// Util
|
||||
const std::string &name(const cell &);
|
||||
uint64_t sequence(const cell &);
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
||||
inline std::ostream &
|
||||
ircd::db::operator<<(std::ostream &s, const cell &c)
|
||||
{
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_COLUMN_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
|
||||
// Columns add the ability to run multiple LevelDB's in synchrony under the same
|
||||
// database (directory). Each column is a fully distinct key/value store; they
|
||||
// are merely joined for consistency and possible performance advantages for
|
||||
|
@ -53,7 +50,42 @@ namespace db {
|
|||
// with both a normal string and binary data, so this class is not a template and
|
||||
// offers no conversions at this level. see: value.h/object.h
|
||||
//
|
||||
struct column
|
||||
namespace ircd::db
|
||||
{
|
||||
struct column;
|
||||
|
||||
// Get property data of a db column. R can optionally be uint64_t for some
|
||||
// values. Refer to RocksDB documentation for more info.
|
||||
template<class R = std::string> R property(column &, const string_view &name);
|
||||
template<> std::string property(column &, const string_view &name);
|
||||
template<> uint64_t property(column &, const string_view &name);
|
||||
|
||||
// Information about a column
|
||||
const std::string &name(const column &);
|
||||
size_t file_count(column &);
|
||||
size_t bytes(column &);
|
||||
|
||||
// [GET] Tests if key exists
|
||||
bool has(column &, const string_view &key, const gopts & = {});
|
||||
|
||||
// [GET] Convenience functions to copy data into your buffer.
|
||||
// The signed char buffer is null terminated; the unsigned is not.
|
||||
size_t read(column &, const string_view &key, uint8_t *const &buf, const size_t &max, const gopts & = {});
|
||||
string_view read(column &, const string_view &key, char *const &buf, const size_t &max, const gopts & = {});
|
||||
std::string read(column &, const string_view &key, const gopts & = {});
|
||||
|
||||
// [SET] Write data to the db
|
||||
void write(column &, const string_view &key, const string_view &value, const sopts & = {});
|
||||
void write(column &, const string_view &key, const uint8_t *const &buf, const size_t &size, const sopts & = {});
|
||||
|
||||
// [SET] Remove data from the db. not_found is never thrown.
|
||||
void del(column &, const string_view &key, const sopts & = {});
|
||||
|
||||
// [SET] Flush memory tables to disk (this column only).
|
||||
void flush(column &, const bool &blocking = false);
|
||||
}
|
||||
|
||||
struct ircd::db::column
|
||||
{
|
||||
struct delta;
|
||||
struct const_iterator;
|
||||
|
@ -121,7 +153,7 @@ struct column
|
|||
// It is unlikely you will need to work with column deltas directly because
|
||||
// you may decohere one column from the others participating in a row.
|
||||
//
|
||||
struct column::delta
|
||||
struct ircd::db::column::delta
|
||||
:std::tuple<op, string_view, string_view>
|
||||
{
|
||||
delta(const string_view &key, const string_view &val, const enum op &op = op::SET)
|
||||
|
@ -139,7 +171,7 @@ struct column::delta
|
|||
// Otherwise, construct an iterator by having it returned from the appropriate
|
||||
// function in column::.
|
||||
//
|
||||
struct column::const_iterator
|
||||
struct ircd::db::column::const_iterator
|
||||
{
|
||||
using value_type = column::value_type;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
@ -184,39 +216,6 @@ struct column::const_iterator
|
|||
friend void seek(column::const_iterator &, const string_view &key);
|
||||
};
|
||||
|
||||
// Get property data of a db column. R can optionally be uint64_t for some
|
||||
// values. Refer to RocksDB documentation for more info.
|
||||
template<class R = std::string> R property(column &, const string_view &name);
|
||||
template<> std::string property(column &, const string_view &name);
|
||||
template<> uint64_t property(column &, const string_view &name);
|
||||
|
||||
// Information about a column
|
||||
const std::string &name(const column &);
|
||||
size_t file_count(column &);
|
||||
size_t bytes(column &);
|
||||
|
||||
// [GET] Tests if key exists
|
||||
bool has(column &, const string_view &key, const gopts & = {});
|
||||
|
||||
// [GET] Convenience functions to copy data into your buffer.
|
||||
// The signed char buffer is null terminated; the unsigned is not.
|
||||
size_t read(column &, const string_view &key, uint8_t *const &buf, const size_t &max, const gopts & = {});
|
||||
string_view read(column &, const string_view &key, char *const &buf, const size_t &max, const gopts & = {});
|
||||
std::string read(column &, const string_view &key, const gopts & = {});
|
||||
|
||||
// [SET] Write data to the db
|
||||
void write(column &, const string_view &key, const string_view &value, const sopts & = {});
|
||||
void write(column &, const string_view &key, const uint8_t *const &buf, const size_t &size, const sopts & = {});
|
||||
|
||||
// [SET] Remove data from the db. not_found is never thrown.
|
||||
void del(column &, const string_view &key, const sopts & = {});
|
||||
|
||||
// [SET] Flush memory tables to disk (this column only).
|
||||
void flush(column &, const bool &blocking = false);
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::db::column::const_iterator::operator
|
||||
database::column &()
|
||||
{
|
||||
|
|
|
@ -23,9 +23,7 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_DATABASE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
|
||||
//
|
||||
// Database instance
|
||||
//
|
||||
// There can be only one instance of this class for each database, so it is
|
||||
|
@ -38,7 +36,19 @@ namespace db {
|
|||
// The instance registers and deregisters itself in a global set of open
|
||||
// databases and can be found that way if necessary.
|
||||
//
|
||||
struct database
|
||||
|
||||
namespace ircd::db
|
||||
{
|
||||
struct database;
|
||||
|
||||
template<class R = uint64_t> R property(database &, const string_view &name);
|
||||
template<> uint64_t property(database &, const string_view &name);
|
||||
const std::string &name(const database &);
|
||||
uint64_t sequence(const database &); // Latest sequence number
|
||||
void sync(database &); // Sync the write log (all columns)
|
||||
}
|
||||
|
||||
struct ircd::db::database
|
||||
:std::enable_shared_from_this<struct database>
|
||||
{
|
||||
struct descriptor;
|
||||
|
@ -90,9 +100,19 @@ struct database
|
|||
static database &get(column &);
|
||||
};
|
||||
|
||||
namespace ircd::db
|
||||
{
|
||||
std::shared_ptr<const database::column> shared_from(const database::column &);
|
||||
std::shared_ptr<database::column> shared_from(database::column &);
|
||||
const std::string &name(const database::column &);
|
||||
uint64_t sequence(const database::snapshot &); // Sequence of a snapshot
|
||||
uint32_t id(const database::column &);
|
||||
void drop(database::column &); // Request to erase column from db
|
||||
}
|
||||
|
||||
// Descriptor of a column when opening database. Database must be opened with
|
||||
// a consistent set of descriptors describing what will be found upon opening.
|
||||
struct database::descriptor
|
||||
struct ircd::db::database::descriptor
|
||||
{
|
||||
using typing = std::pair<std::type_index, std::type_index>;
|
||||
|
||||
|
@ -104,7 +124,7 @@ struct database::descriptor
|
|||
};
|
||||
|
||||
// options <-> string
|
||||
struct database::options
|
||||
struct ircd::db::database::options
|
||||
:std::string
|
||||
{
|
||||
struct map;
|
||||
|
@ -129,7 +149,7 @@ struct database::options
|
|||
};
|
||||
|
||||
// options <-> map
|
||||
struct database::options::map
|
||||
struct ircd::db::database::options::map
|
||||
:std::unordered_map<std::string, std::string>
|
||||
{
|
||||
// Output of options structures from map
|
||||
|
@ -147,7 +167,7 @@ struct database::options::map
|
|||
{}
|
||||
};
|
||||
|
||||
struct database::snapshot
|
||||
struct ircd::db::database::snapshot
|
||||
{
|
||||
std::shared_ptr<const rocksdb::Snapshot> s;
|
||||
|
||||
|
@ -161,25 +181,3 @@ struct database::snapshot
|
|||
snapshot() = default;
|
||||
~snapshot() noexcept;
|
||||
};
|
||||
|
||||
// Linkage to get shared_ptr of database::column
|
||||
std::shared_ptr<const database::column> shared_from(const database::column &);
|
||||
std::shared_ptr<database::column> shared_from(database::column &);
|
||||
|
||||
// Get property data from all columns in DB. Only integer properties supported.
|
||||
template<class R = uint64_t> R property(database &, const string_view &name);
|
||||
template<> uint64_t property(database &, const string_view &name);
|
||||
|
||||
const std::string &name(const database &);
|
||||
const std::string &name(const database::column &);
|
||||
|
||||
uint64_t sequence(const database::snapshot &); // Sequence of a snapshot
|
||||
uint64_t sequence(const database &); // Latest sequence number
|
||||
|
||||
uint32_t id(const database::column &);
|
||||
void drop(database::column &); // Request to erase column from db
|
||||
|
||||
void sync(database &); // Sync the write log (all columns)
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
|
|
@ -23,33 +23,32 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_DELTA_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
|
||||
enum op
|
||||
namespace ircd::db
|
||||
{
|
||||
GET, // no-op sentinel, do not use (debug asserts)
|
||||
SET, // (batch.Put)
|
||||
MERGE, // (batch.Merge)
|
||||
DELETE, // (batch.Delete)
|
||||
DELETE_RANGE, // (batch.DeleteRange)
|
||||
SINGLE_DELETE, // (batch.SingleDelete)
|
||||
};
|
||||
enum op
|
||||
{
|
||||
GET, // no-op sentinel, do not use (debug asserts)
|
||||
SET, // (batch.Put)
|
||||
MERGE, // (batch.Merge)
|
||||
DELETE, // (batch.Delete)
|
||||
DELETE_RANGE, // (batch.DeleteRange)
|
||||
SINGLE_DELETE, // (batch.SingleDelete)
|
||||
};
|
||||
|
||||
// Indicates an op uses both a key and value for its operation. Some only use
|
||||
// a key name so an empty value argument in a delta is okay when false.
|
||||
bool value_required(const op &op);
|
||||
// Indicates an op uses both a key and value for its operation. Some only use
|
||||
// a key name so an empty value argument in a delta is okay when false.
|
||||
bool value_required(const op &op);
|
||||
|
||||
using merge_delta = std::pair<string_view, string_view>;
|
||||
using merge_closure = std::function<std::string (const string_view &key, const merge_delta &)>;
|
||||
using update_closure = std::function<std::string (const string_view &key, merge_delta &)>;
|
||||
using merge_delta = std::pair<string_view, string_view>;
|
||||
using merge_closure = std::function<std::string (const string_view &key, const merge_delta &)>;
|
||||
using update_closure = std::function<std::string (const string_view &key, merge_delta &)>;
|
||||
|
||||
struct comparator
|
||||
struct comparator;
|
||||
}
|
||||
|
||||
struct ircd::db::comparator
|
||||
{
|
||||
std::string name;
|
||||
std::function<bool (const string_view &, const string_view &)> less;
|
||||
std::function<bool (const string_view &, const string_view &)> equal;
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
|
|
@ -23,28 +23,35 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_OPTS_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
template<class T> struct optval;
|
||||
template<class T> using optlist = std::initializer_list<optval<T>>;
|
||||
template<class T> bool has_opt(const optlist<T> &, const T &);
|
||||
template<class T> ssize_t opt_val(const optlist<T> &, const T &);
|
||||
|
||||
enum class set;
|
||||
struct sopts;
|
||||
|
||||
enum class get;
|
||||
struct gopts;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct optval
|
||||
struct ircd::db::optval
|
||||
:std::pair<T, ssize_t>
|
||||
{
|
||||
optval(const T &key, const ssize_t &val = std::numeric_limits<ssize_t>::min());
|
||||
};
|
||||
|
||||
template<class T> using optlist = std::initializer_list<optval<T>>;
|
||||
template<class T> bool has_opt(const optlist<T> &, const T &);
|
||||
template<class T> ssize_t opt_val(const optlist<T> &, const T &);
|
||||
|
||||
enum class set
|
||||
enum class ircd::db::set
|
||||
{
|
||||
FSYNC, // Uses kernel filesystem synchronization after write (slow)
|
||||
NO_JOURNAL, // Write Ahead Log (WAL) for some crash recovery
|
||||
MISSING_COLUMNS // No exception thrown when writing to a deleted column family
|
||||
};
|
||||
|
||||
struct sopts
|
||||
struct ircd::db::sopts
|
||||
:optlist<set>
|
||||
{
|
||||
template<class... list>
|
||||
|
@ -53,7 +60,7 @@ struct sopts
|
|||
{}
|
||||
};
|
||||
|
||||
enum class get
|
||||
enum class ircd::db::get
|
||||
{
|
||||
PIN, // Keep iter data in memory for iter lifetime (good for lots of ++/--)
|
||||
CACHE, // Update the cache (CACHE is default for non-iterator operations)
|
||||
|
@ -64,7 +71,7 @@ enum class get
|
|||
NO_EMPTY, // Option for db::row to not include unassigned cells in the row
|
||||
};
|
||||
|
||||
struct gopts
|
||||
struct ircd::db::gopts
|
||||
:optlist<get>
|
||||
{
|
||||
database::snapshot snapshot;
|
||||
|
@ -75,9 +82,6 @@ struct gopts
|
|||
{}
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
||||
template<class T>
|
||||
ssize_t
|
||||
ircd::db::opt_val(const optlist<T> &list,
|
||||
|
|
|
@ -23,8 +23,13 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_ROW_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
struct row;
|
||||
|
||||
// [SET] Delete row from DB (convenience to an op::DELETE delta)
|
||||
void del(row &, const sopts & = {});
|
||||
}
|
||||
|
||||
// A `row` is a collection of cells from different columns which all share the same
|
||||
// key. This is an interface for dealing with those cells in the aggregate.
|
||||
|
@ -33,7 +38,7 @@ namespace db {
|
|||
// will all return the same index value across the whole `row`. To get the names
|
||||
// of the columns themselves to build ex. the key name of a JSON key-value pair,
|
||||
// use `cell::col()`, which will be different for each `cell` across the `row`.
|
||||
struct row
|
||||
struct ircd::db::row
|
||||
{
|
||||
struct delta;
|
||||
struct iterator;
|
||||
|
@ -84,7 +89,17 @@ struct row
|
|||
friend size_t trim(row &); // remove invalid
|
||||
};
|
||||
|
||||
struct row::const_iterator
|
||||
namespace ircd::db
|
||||
{
|
||||
// [SET] Perform operations in a sequence as a single transaction. No template
|
||||
// iterators supported yet, just a ptr range good for contiguous sequences.
|
||||
void write(const row::delta *const &begin, const row::delta *const &end, const sopts & = {});
|
||||
void write(const std::initializer_list<row::delta> &, const sopts & = {});
|
||||
void write(const sopts &, const std::initializer_list<row::delta> &);
|
||||
void write(const row::delta &, const sopts & = {});
|
||||
}
|
||||
|
||||
struct ircd::db::row::const_iterator
|
||||
{
|
||||
using value_type = const cell &;
|
||||
using reference = const cell &;
|
||||
|
@ -113,7 +128,7 @@ struct row::const_iterator
|
|||
friend bool operator!=(const const_iterator &, const const_iterator &);
|
||||
};
|
||||
|
||||
struct row::iterator
|
||||
struct ircd::db::row::iterator
|
||||
{
|
||||
using value_type = cell &;
|
||||
using reference = cell &;
|
||||
|
@ -148,7 +163,7 @@ struct row::iterator
|
|||
// useful to make a commitment on a single row as a convenient way to compose
|
||||
// all of a row's cells together.
|
||||
//
|
||||
struct row::delta
|
||||
struct ircd::db::row::delta
|
||||
:std::tuple<op, row &>
|
||||
{
|
||||
delta(row &r, const enum op &op = op::SET)
|
||||
|
@ -160,19 +175,6 @@ struct row::delta
|
|||
{}
|
||||
};
|
||||
|
||||
// [SET] Perform operations in a sequence as a single transaction. No template
|
||||
// iterators supported yet, just a ptr range good for contiguous sequences.
|
||||
void write(const row::delta *const &begin, const row::delta *const &end, const sopts & = {});
|
||||
void write(const std::initializer_list<row::delta> &, const sopts & = {});
|
||||
void write(const sopts &, const std::initializer_list<row::delta> &);
|
||||
void write(const row::delta &, const sopts & = {});
|
||||
|
||||
// [SET] Delete row from DB (convenience to an op::DELETE delta)
|
||||
void del(row &, const sopts & = {});
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::db::cell &
|
||||
ircd::db::row::operator[](const string_view &column)
|
||||
{
|
||||
|
|
|
@ -23,17 +23,22 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_DB_VALUE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace db {
|
||||
namespace ircd::db
|
||||
{
|
||||
template<database *const &d, class T = string_view> struct value;
|
||||
template<database *const &d> struct value<d, void>;
|
||||
template<database *const &d> struct value<d, string_view>;
|
||||
template<database *const &d, class T> struct arithmetic_value;
|
||||
}
|
||||
|
||||
template<database *const &d,
|
||||
class T = string_view>
|
||||
struct value
|
||||
template<ircd::db::database *const &d,
|
||||
class T>
|
||||
struct ircd::db::value
|
||||
{
|
||||
};
|
||||
|
||||
template<database *const &d>
|
||||
struct value<d, void>
|
||||
template<ircd::db::database *const &d>
|
||||
struct ircd::db::value<d, void>
|
||||
:cell
|
||||
{
|
||||
using cell::cell;
|
||||
|
@ -44,8 +49,8 @@ struct value<d, void>
|
|||
{}
|
||||
};
|
||||
|
||||
template<database *const &d>
|
||||
struct value<d, string_view>
|
||||
template<ircd::db::database *const &d>
|
||||
struct ircd::db::value<d, ircd::string_view>
|
||||
:value<d, void>
|
||||
{
|
||||
operator string_view() const
|
||||
|
@ -78,9 +83,9 @@ struct value<d, string_view>
|
|||
}
|
||||
};
|
||||
|
||||
template<database *const &d,
|
||||
template<ircd::db::database *const &d,
|
||||
class T>
|
||||
struct arithmetic_value
|
||||
struct ircd::db::arithmetic_value
|
||||
:value<d, void>
|
||||
{
|
||||
bool compare_exchange(T &expected, const T &desired)
|
||||
|
@ -143,12 +148,12 @@ struct value<d, _type_> \
|
|||
using arithmetic_value<d, _type_>::arithmetic_value; \
|
||||
}
|
||||
|
||||
IRCD_ARITHMETIC_VALUE(uint64_t);
|
||||
IRCD_ARITHMETIC_VALUE(int64_t);
|
||||
IRCD_ARITHMETIC_VALUE(uint32_t);
|
||||
IRCD_ARITHMETIC_VALUE(int32_t);
|
||||
IRCD_ARITHMETIC_VALUE(uint16_t);
|
||||
IRCD_ARITHMETIC_VALUE(int16_t);
|
||||
|
||||
} // namespace db
|
||||
} // namespace ircd
|
||||
namespace ircd::db
|
||||
{
|
||||
IRCD_ARITHMETIC_VALUE(uint64_t);
|
||||
IRCD_ARITHMETIC_VALUE(int64_t);
|
||||
IRCD_ARITHMETIC_VALUE(uint32_t);
|
||||
IRCD_ARITHMETIC_VALUE(int32_t);
|
||||
IRCD_ARITHMETIC_VALUE(uint16_t);
|
||||
IRCD_ARITHMETIC_VALUE(int16_t);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_EXCEPTION_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
struct exception;
|
||||
}
|
||||
|
||||
/** The root exception type.
|
||||
*
|
||||
|
@ -47,7 +50,7 @@ namespace ircd {
|
|||
* Note: Prefer 'noexcept' instead of catch(...), noexcept is like an 'assert'
|
||||
* for exceptions, and the rogue can be found-out in testing.
|
||||
*/
|
||||
struct exception
|
||||
struct ircd::exception
|
||||
:std::exception
|
||||
{
|
||||
protected:
|
||||
|
@ -142,7 +145,8 @@ struct name \
|
|||
*
|
||||
* IRCD_EXCEPTION(ircd::error, error)
|
||||
*/
|
||||
IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad")
|
||||
IRCD_EXCEPTION(error, user_error) // throw ircd::user_error("something silly")
|
||||
|
||||
} // namespace ircd
|
||||
namespace ircd
|
||||
{
|
||||
IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad")
|
||||
IRCD_EXCEPTION(error, user_error) // throw ircd::user_error("something silly")
|
||||
}
|
||||
|
|
|
@ -22,31 +22,38 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_FMT_H
|
||||
|
||||
namespace ircd {
|
||||
namespace fmt {
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error);
|
||||
IRCD_EXCEPTION(error, invalid_format);
|
||||
IRCD_EXCEPTION(error, invalid_type);
|
||||
IRCD_EXCEPTION(error, illegal);
|
||||
|
||||
//
|
||||
// Module API
|
||||
//
|
||||
constexpr char SPECIFIER
|
||||
namespace ircd::fmt
|
||||
{
|
||||
'%'
|
||||
};
|
||||
IRCD_EXCEPTION(ircd::error, error);
|
||||
IRCD_EXCEPTION(error, invalid_format);
|
||||
IRCD_EXCEPTION(error, invalid_type);
|
||||
IRCD_EXCEPTION(error, illegal);
|
||||
|
||||
constexpr char SPECIFIER_TERMINATOR
|
||||
{
|
||||
'$'
|
||||
};
|
||||
struct spec;
|
||||
struct specifier;
|
||||
struct snprintf;
|
||||
struct vsnprintf;
|
||||
|
||||
using arg = std::tuple<const void *, std::type_index>;
|
||||
//
|
||||
// Module API
|
||||
//
|
||||
constexpr char SPECIFIER
|
||||
{
|
||||
'%'
|
||||
};
|
||||
|
||||
constexpr char SPECIFIER_TERMINATOR
|
||||
{
|
||||
'$'
|
||||
};
|
||||
|
||||
using arg = std::tuple<const void *, std::type_index>;
|
||||
|
||||
const std::map<string_view, specifier *, std::less<>> &specifiers();
|
||||
}
|
||||
|
||||
// Structural representation of a format specifier
|
||||
struct spec
|
||||
struct ircd::fmt::spec
|
||||
{
|
||||
char sign {'+'};
|
||||
ushort width {0};
|
||||
|
@ -57,7 +64,7 @@ struct spec
|
|||
|
||||
// A format specifier handler module.
|
||||
// This allows a new "%foo" to be defined with custom handling.
|
||||
class specifier
|
||||
class ircd::fmt::specifier
|
||||
{
|
||||
std::set<std::string> names;
|
||||
|
||||
|
@ -69,15 +76,13 @@ class specifier
|
|||
virtual ~specifier() noexcept;
|
||||
};
|
||||
|
||||
const std::map<string_view, specifier *, std::less<>> &specifiers();
|
||||
|
||||
//
|
||||
// User API
|
||||
//
|
||||
|
||||
// * The arguments are not restricted by stdarg limitations. You can pass a real std::string.
|
||||
// * The function participates in the custom protocol-safe ruleset.
|
||||
class snprintf
|
||||
class ircd::fmt::snprintf
|
||||
{
|
||||
const char *fstart; // Current running position in the fmtstr
|
||||
const char *fstop; // Saved state from the last position
|
||||
|
@ -113,7 +118,7 @@ class snprintf
|
|||
}{}
|
||||
};
|
||||
|
||||
struct vsnprintf
|
||||
struct ircd::fmt::vsnprintf
|
||||
:snprintf
|
||||
{
|
||||
vsnprintf(char *const &buf,
|
||||
|
@ -125,6 +130,3 @@ struct vsnprintf
|
|||
internal, buf, max, fmt, ap
|
||||
}{}
|
||||
};
|
||||
|
||||
} // namespace fmt
|
||||
} // namespace ircd
|
||||
|
|
|
@ -36,66 +36,62 @@
|
|||
* AUTOMODPATH = directory for autoloaded modules
|
||||
*/
|
||||
|
||||
namespace ircd {
|
||||
namespace fs {
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, filesystem_error)
|
||||
|
||||
constexpr auto DPATH = IRCD_PREFIX;
|
||||
constexpr auto BINPATH = IRCD_PREFIX "/bin";
|
||||
constexpr auto MODPATH = RB_MODULE_DIR;
|
||||
constexpr auto ETCPATH = RB_ETC_DIR;
|
||||
constexpr auto LOGPATH = RB_LOG_DIR;
|
||||
constexpr auto UHPATH = RB_HELP_DIR "/users";
|
||||
constexpr auto HPATH = RB_HELP_DIR "/opers";
|
||||
constexpr auto SPATH = RB_BIN_DIR "/" BRANDING_NAME; // ircd executable
|
||||
constexpr auto CPATH = RB_ETC_DIR "/ircd.conf"; // ircd.conf file
|
||||
constexpr auto MPATH = RB_ETC_DIR "/ircd.motd"; // MOTD file
|
||||
constexpr auto LPATH = RB_LOG_DIR "/ircd.log"; // ircd logfile
|
||||
constexpr auto OPATH = RB_ETC_DIR "/opers.motd"; // oper MOTD file
|
||||
constexpr auto DBPATH = PKGLOCALSTATEDIR "/db"; // database prefix
|
||||
constexpr auto BDBPATH = PKGLOCALSTATEDIR "/ban.db"; // bandb file
|
||||
|
||||
// Below are the elements for default paths.
|
||||
enum index
|
||||
namespace ircd::fs
|
||||
{
|
||||
PREFIX,
|
||||
BIN,
|
||||
ETC,
|
||||
LOG,
|
||||
LIBEXEC,
|
||||
MODULES,
|
||||
USERHELP,
|
||||
OPERHELP,
|
||||
IRCD_CONF,
|
||||
IRCD_EXEC,
|
||||
IRCD_MOTD,
|
||||
IRCD_LOG,
|
||||
IRCD_OMOTD,
|
||||
BANDB,
|
||||
DB,
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, filesystem_error)
|
||||
|
||||
_NUM_
|
||||
};
|
||||
constexpr auto DPATH = IRCD_PREFIX;
|
||||
constexpr auto BINPATH = IRCD_PREFIX "/bin";
|
||||
constexpr auto MODPATH = RB_MODULE_DIR;
|
||||
constexpr auto ETCPATH = RB_ETC_DIR;
|
||||
constexpr auto LOGPATH = RB_LOG_DIR;
|
||||
constexpr auto UHPATH = RB_HELP_DIR "/users";
|
||||
constexpr auto HPATH = RB_HELP_DIR "/opers";
|
||||
constexpr auto SPATH = RB_BIN_DIR "/" BRANDING_NAME; // ircd executable
|
||||
constexpr auto CPATH = RB_ETC_DIR "/ircd.conf"; // ircd.conf file
|
||||
constexpr auto MPATH = RB_ETC_DIR "/ircd.motd"; // MOTD file
|
||||
constexpr auto LPATH = RB_LOG_DIR "/ircd.log"; // ircd logfile
|
||||
constexpr auto OPATH = RB_ETC_DIR "/opers.motd"; // oper MOTD file
|
||||
constexpr auto DBPATH = PKGLOCALSTATEDIR "/db"; // database prefix
|
||||
constexpr auto BDBPATH = PKGLOCALSTATEDIR "/ban.db"; // bandb file
|
||||
|
||||
const char *get(index) noexcept;
|
||||
const char *name(index) noexcept;
|
||||
// Below are the elements for default paths.
|
||||
enum index
|
||||
{
|
||||
PREFIX,
|
||||
BIN,
|
||||
ETC,
|
||||
LOG,
|
||||
LIBEXEC,
|
||||
MODULES,
|
||||
USERHELP,
|
||||
OPERHELP,
|
||||
IRCD_CONF,
|
||||
IRCD_EXEC,
|
||||
IRCD_MOTD,
|
||||
IRCD_LOG,
|
||||
IRCD_OMOTD,
|
||||
BANDB,
|
||||
DB,
|
||||
_NUM_
|
||||
};
|
||||
|
||||
std::string make_path(const std::initializer_list<std::string> &);
|
||||
const char *get(index) noexcept;
|
||||
const char *name(index) noexcept;
|
||||
|
||||
bool exists(const std::string &path);
|
||||
bool is_dir(const std::string &path);
|
||||
bool is_reg(const std::string &path);
|
||||
std::string make_path(const std::initializer_list<std::string> &);
|
||||
|
||||
std::vector<std::string> ls(const std::string &path);
|
||||
std::vector<std::string> ls_recursive(const std::string &path);
|
||||
bool exists(const std::string &path);
|
||||
bool is_dir(const std::string &path);
|
||||
bool is_reg(const std::string &path);
|
||||
|
||||
std::string cwd();
|
||||
void chdir(const std::string &path);
|
||||
bool mkdir(const std::string &path);
|
||||
std::vector<std::string> ls(const std::string &path);
|
||||
std::vector<std::string> ls_recursive(const std::string &path);
|
||||
|
||||
std::string read(const std::string &name);
|
||||
std::string cwd();
|
||||
void chdir(const std::string &path);
|
||||
bool mkdir(const std::string &path);
|
||||
|
||||
} // namespace fs
|
||||
} // namespace ircd
|
||||
std::string read(const std::string &name);
|
||||
}
|
||||
|
|
|
@ -25,13 +25,26 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_HTTP_H
|
||||
|
||||
namespace ircd {
|
||||
namespace http {
|
||||
namespace ircd::http
|
||||
{
|
||||
enum code :int;
|
||||
struct error;
|
||||
struct line;
|
||||
struct query;
|
||||
struct headers;
|
||||
struct content;
|
||||
struct request;
|
||||
struct response;
|
||||
|
||||
extern std::map<code, string_view> reason;
|
||||
enum code status(const string_view &);
|
||||
}
|
||||
|
||||
//
|
||||
// Add more as you go...
|
||||
//
|
||||
enum code
|
||||
enum ircd::http::code
|
||||
:int
|
||||
{
|
||||
CONTINUE = 100,
|
||||
SWITCHING_PROTOCOLS = 101,
|
||||
|
@ -71,10 +84,7 @@ enum code
|
|||
INSUFFICIENT_STORAGE = 507,
|
||||
};
|
||||
|
||||
extern std::map<code, string_view> reason;
|
||||
enum code status(const string_view &);
|
||||
|
||||
struct error
|
||||
struct ircd::http::error
|
||||
:ircd::error
|
||||
{
|
||||
enum code code;
|
||||
|
@ -83,7 +93,7 @@ struct error
|
|||
error(const enum code &, std::string content = {});
|
||||
};
|
||||
|
||||
struct line
|
||||
struct ircd::http::line
|
||||
:string_view
|
||||
{
|
||||
struct request;
|
||||
|
@ -94,7 +104,7 @@ struct line
|
|||
line(parse::capstan &);
|
||||
};
|
||||
|
||||
struct line::request
|
||||
struct ircd::http::line::request
|
||||
{
|
||||
string_view method;
|
||||
string_view path;
|
||||
|
@ -106,7 +116,7 @@ struct line::request
|
|||
request() = default;
|
||||
};
|
||||
|
||||
struct line::response
|
||||
struct ircd::http::line::response
|
||||
{
|
||||
string_view version;
|
||||
string_view status;
|
||||
|
@ -116,7 +126,7 @@ struct line::response
|
|||
response() = default;
|
||||
};
|
||||
|
||||
struct query
|
||||
struct ircd::http::query
|
||||
:std::pair<string_view, string_view>
|
||||
{
|
||||
struct string;
|
||||
|
@ -130,7 +140,7 @@ struct query
|
|||
|
||||
// Query string is read as a complete string off the tape (into request.query) and
|
||||
// not parsed further. To make queries into that string use this class to view it.
|
||||
struct query::string
|
||||
struct ircd::http::query::string
|
||||
:string_view
|
||||
{
|
||||
void for_each(const std::function<void (const query &)> &) const;
|
||||
|
@ -142,7 +152,7 @@ struct query::string
|
|||
using string_view::string_view;
|
||||
};
|
||||
|
||||
struct line::header
|
||||
struct ircd::http::line::header
|
||||
:std::pair<string_view, string_view>
|
||||
{
|
||||
bool operator<(const string_view &s) const { return iless(first, s); }
|
||||
|
@ -154,7 +164,7 @@ struct line::header
|
|||
};
|
||||
|
||||
// HTTP headers are read once off the tape and proffered to the closure.
|
||||
struct headers
|
||||
struct ircd::http::headers
|
||||
{
|
||||
using closure = std::function<void (const line::header &)>;
|
||||
|
||||
|
@ -164,7 +174,7 @@ struct headers
|
|||
// Use the request::content / response::content wrappers. They ensure the proper amount
|
||||
// of content is read and the tape is in the right position for the next request
|
||||
// with exception safety.
|
||||
struct content
|
||||
struct ircd::http::content
|
||||
:string_view
|
||||
{
|
||||
IRCD_OVERLOAD(discard)
|
||||
|
@ -174,7 +184,7 @@ struct content
|
|||
content() = default;
|
||||
};
|
||||
|
||||
struct response
|
||||
struct ircd::http::response
|
||||
{
|
||||
struct head;
|
||||
struct content;
|
||||
|
@ -193,7 +203,7 @@ struct response
|
|||
const headers::closure & = {});
|
||||
};
|
||||
|
||||
struct response::head
|
||||
struct ircd::http::response::head
|
||||
:line::response
|
||||
{
|
||||
size_t content_length {0};
|
||||
|
@ -201,7 +211,7 @@ struct response::head
|
|||
head(parse::capstan &pc, const headers::closure &c = {});
|
||||
};
|
||||
|
||||
struct response::content
|
||||
struct ircd::http::response::content
|
||||
:http::content
|
||||
{
|
||||
content(parse::capstan &pc, const head &h, discard_t)
|
||||
|
@ -215,7 +225,7 @@ struct response::content
|
|||
content() = default;
|
||||
};
|
||||
|
||||
struct request
|
||||
struct ircd::http::request
|
||||
{
|
||||
struct head;
|
||||
struct content;
|
||||
|
@ -238,7 +248,7 @@ struct request
|
|||
const headers::closure & = {});
|
||||
};
|
||||
|
||||
struct request::head
|
||||
struct ircd::http::request::head
|
||||
:line::request
|
||||
{
|
||||
string_view host;
|
||||
|
@ -249,7 +259,7 @@ struct request::head
|
|||
head(parse::capstan &pc, const headers::closure &c = {});
|
||||
};
|
||||
|
||||
struct request::content
|
||||
struct ircd::http::request::content
|
||||
:http::content
|
||||
{
|
||||
content(parse::capstan &pc, const head &h, discard_t)
|
||||
|
@ -260,6 +270,3 @@ struct request::content
|
|||
:http::content{pc, h.content_length}
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace ircd
|
||||
|
|
|
@ -23,29 +23,28 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_INFO_H
|
||||
|
||||
namespace ircd {
|
||||
namespace info {
|
||||
namespace ircd::info
|
||||
{
|
||||
struct line;
|
||||
|
||||
struct line
|
||||
extern const std::vector<info::line> myinfo;
|
||||
extern const std::vector<std::string> credits;
|
||||
extern const std::string serno;
|
||||
extern const std::string version;
|
||||
extern const char *const ircd_version; // legacy
|
||||
|
||||
extern const time_t configured_time;
|
||||
extern const time_t compiled_time;
|
||||
extern const time_t startup_time;
|
||||
extern const std::string compiled;
|
||||
extern const std::string configured;
|
||||
extern const std::string startup;
|
||||
}
|
||||
|
||||
struct ircd::info::line
|
||||
{
|
||||
std::string key;
|
||||
std::string valstr;
|
||||
uint64_t valnum;
|
||||
std::string desc;
|
||||
};
|
||||
|
||||
extern const std::vector<info::line> myinfo;
|
||||
extern const std::vector<std::string> credits;
|
||||
extern const std::string serno;
|
||||
extern const std::string version;
|
||||
extern const char *const ircd_version; // legacy
|
||||
|
||||
extern const time_t configured_time;
|
||||
extern const time_t compiled_time;
|
||||
extern const time_t startup_time;
|
||||
extern const std::string compiled;
|
||||
extern const std::string configured;
|
||||
extern const std::string startup;
|
||||
|
||||
} // namespace info
|
||||
} // namespace ircd
|
||||
|
|
|
@ -31,44 +31,43 @@
|
|||
#include "stdinc.h"
|
||||
#endif
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
extern bool debugmode; // Toggled by command line to indicate debug behavior
|
||||
extern const bool &main_exited; // Set when main context has finished.
|
||||
|
||||
extern bool debugmode; // Toggled by command line to indicate debug behavior
|
||||
extern const bool &main_exited; // Set when main context has finished.
|
||||
// The signature of the callback indicating when IRCd's main context has completed.
|
||||
using main_exit_cb = std::function<void ()>;
|
||||
|
||||
// The signature of the callback indicating when IRCd's main context has completed.
|
||||
using main_exit_cb = std::function<void ()>;
|
||||
//
|
||||
// Sets up the IRCd, handlers (main context), and then returns without blocking.
|
||||
// Pass your io_service instance, it will share it with the rest of your program.
|
||||
// An exception will be thrown on error.
|
||||
//
|
||||
// This function will setup the main program loop of libircd. The execution will
|
||||
// occur when your io_service.run() or poll() is further invoked. For an explanation
|
||||
// of the callback, see the documentation for ircd::stop().
|
||||
//
|
||||
void init(boost::asio::io_service &ios, const std::string &newconf_path, main_exit_cb = nullptr);
|
||||
|
||||
//
|
||||
// Sets up the IRCd, handlers (main context), and then returns without blocking.
|
||||
// Pass your io_service instance, it will share it with the rest of your program.
|
||||
// An exception will be thrown on error.
|
||||
//
|
||||
// This function will setup the main program loop of libircd. The execution will
|
||||
// occur when your io_service.run() or poll() is further invoked. For an explanation
|
||||
// of the callback, see the documentation for ircd::stop().
|
||||
//
|
||||
void init(boost::asio::io_service &ios, const std::string &newconf_path, main_exit_cb = nullptr);
|
||||
//
|
||||
// Notifies IRCd to shutdown. A shutdown will occur asynchronously and this
|
||||
// function will return immediately. main_exit_cb will be called when IRCd
|
||||
// has no more work for the ios (main_exit_cb will be the last operation from
|
||||
// IRCd posted to the ios).
|
||||
//
|
||||
// This function is the proper way to shutdown libircd after an init(), and while
|
||||
// your io_service.run() is invoked without stopping your io_service shared by
|
||||
// other activities unrelated to libircd. If your io_service has no other activities
|
||||
// the run() will then return.
|
||||
//
|
||||
// This is useful when your other activities prevent run() from returning.
|
||||
//
|
||||
void stop();
|
||||
|
||||
//
|
||||
// Notifies IRCd to shutdown. A shutdown will occur asynchronously and this
|
||||
// function will return immediately. main_exit_cb will be called when IRCd
|
||||
// has no more work for the ios (main_exit_cb will be the last operation from
|
||||
// IRCd posted to the ios).
|
||||
//
|
||||
// This function is the proper way to shutdown libircd after an init(), and while
|
||||
// your io_service.run() is invoked without stopping your io_service shared by
|
||||
// other activities unrelated to libircd. If your io_service has no other activities
|
||||
// the run() will then return.
|
||||
//
|
||||
// This is useful when your other activities prevent run() from returning.
|
||||
//
|
||||
void stop();
|
||||
|
||||
//
|
||||
// Replaces the callback passed to init() which will indicate libircd completion.
|
||||
// This can be called anytime between init() and stop() to make that replacement.
|
||||
//
|
||||
void at_main_exit(main_exit_cb);
|
||||
|
||||
} // namespace ircd
|
||||
//
|
||||
// Replaces the callback passed to init() which will indicate libircd completion.
|
||||
// This can be called anytime between init() and stop() to make that replacement.
|
||||
//
|
||||
void at_main_exit(main_exit_cb);
|
||||
}
|
||||
|
|
|
@ -56,36 +56,33 @@
|
|||
// proven* output safety. In other words, the grammar prevents exploits like
|
||||
// injecting and terminating JSON as it composes the output.
|
||||
//
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error);
|
||||
IRCD_EXCEPTION(error, parse_error);
|
||||
IRCD_EXCEPTION(error, print_error);
|
||||
IRCD_EXCEPTION(error, type_error);
|
||||
IRCD_EXCEPTION(error, not_found);
|
||||
|
||||
struct array;
|
||||
struct object;
|
||||
struct value;
|
||||
struct index;
|
||||
|
||||
enum type
|
||||
namespace ircd::json
|
||||
{
|
||||
STRING = 0,
|
||||
OBJECT = 1,
|
||||
ARRAY = 2,
|
||||
NUMBER = 3,
|
||||
LITERAL = 4,
|
||||
};
|
||||
enum type type(const string_view &);
|
||||
enum type type(const string_view &, std::nothrow_t);
|
||||
IRCD_EXCEPTION(ircd::error, error);
|
||||
IRCD_EXCEPTION(error, parse_error);
|
||||
IRCD_EXCEPTION(error, print_error);
|
||||
IRCD_EXCEPTION(error, type_error);
|
||||
IRCD_EXCEPTION(error, not_found);
|
||||
|
||||
using path = std::initializer_list<string_view>;
|
||||
std::ostream &operator<<(std::ostream &, const path &);
|
||||
struct array;
|
||||
struct object;
|
||||
struct value;
|
||||
struct index;
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
enum type
|
||||
{
|
||||
STRING = 0,
|
||||
OBJECT = 1,
|
||||
ARRAY = 2,
|
||||
NUMBER = 3,
|
||||
LITERAL = 4,
|
||||
};
|
||||
enum type type(const string_view &);
|
||||
enum type type(const string_view &, std::nothrow_t);
|
||||
|
||||
using path = std::initializer_list<string_view>;
|
||||
std::ostream &operator<<(std::ostream &, const path &);
|
||||
}
|
||||
|
||||
#include "json/array.h"
|
||||
#include "json/object.h"
|
||||
|
@ -93,11 +90,10 @@ std::ostream &operator<<(std::ostream &, const path &);
|
|||
#include "json/index.h"
|
||||
#include "json/tuple.h"
|
||||
|
||||
namespace ircd {
|
||||
|
||||
using json::operator<<;
|
||||
|
||||
} // namespace ircd
|
||||
namespace ircd
|
||||
{
|
||||
using json::operator<<;
|
||||
}
|
||||
|
||||
inline std::ostream &
|
||||
ircd::json::operator<<(std::ostream &s, const path &p)
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_ARRAY_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
// ircd::json::array is the rank1 analog to ircd::json::object. It accepts
|
||||
// queries with numerical indexing. The same parsing approach is used in
|
||||
// ircd::json::object and that is important to note here: iterating this array
|
||||
|
@ -34,7 +31,7 @@ namespace json {
|
|||
// array from the beginning on every single iteration. Instead, use the
|
||||
// provided iterator object.
|
||||
//
|
||||
struct array
|
||||
struct ircd::json::array
|
||||
:string_view
|
||||
{
|
||||
struct const_iterator;
|
||||
|
@ -65,7 +62,7 @@ struct array
|
|||
friend std::ostream &operator<<(std::ostream &, const array &);
|
||||
};
|
||||
|
||||
struct array::const_iterator
|
||||
struct ircd::json::array::const_iterator
|
||||
{
|
||||
using value_type = const string_view;
|
||||
using pointer = value_type *;
|
||||
|
@ -99,9 +96,6 @@ struct array::const_iterator
|
|||
friend bool operator>(const const_iterator &, const const_iterator &);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::array::operator[](const size_t &i)
|
||||
const
|
||||
|
|
|
@ -22,10 +22,7 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_INDEX_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
struct index
|
||||
struct ircd::json::index
|
||||
{
|
||||
struct member;
|
||||
struct const_iterator;
|
||||
|
@ -78,7 +75,7 @@ struct index
|
|||
friend std::ostream &operator<<(std::ostream &, const index &);
|
||||
};
|
||||
|
||||
struct index::member
|
||||
struct ircd::json::index::member
|
||||
:std::pair<value, value>
|
||||
{
|
||||
template<class K> member(const K &k, std::initializer_list<member> v);
|
||||
|
@ -98,7 +95,7 @@ struct index::member
|
|||
friend std::ostream &operator<<(std::ostream &, const member &);
|
||||
};
|
||||
|
||||
struct index::const_iterator
|
||||
struct ircd::json::index::const_iterator
|
||||
{
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
|
@ -129,9 +126,6 @@ struct index::const_iterator
|
|||
friend bool operator<(const const_iterator &a, const const_iterator &b);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline const ircd::json::value &
|
||||
ircd::json::index::operator[](const string_view &name)
|
||||
const
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_OBJECT_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
namespace ircd::json
|
||||
{
|
||||
struct object;
|
||||
}
|
||||
|
||||
// ircd::json::object is an extremely lightweight device for making
|
||||
// queries into a string of JSON. This is a read-only device. It is merely
|
||||
|
@ -61,7 +63,7 @@ namespace json {
|
|||
// use an initializer_list typedef'ed as `path` and those overloads will be
|
||||
// recursive.
|
||||
//
|
||||
struct object
|
||||
struct ircd::json::object
|
||||
:string_view
|
||||
{
|
||||
struct member;
|
||||
|
@ -114,7 +116,7 @@ struct object
|
|||
friend size_t print(char *const &buf, const size_t &max, const object &);
|
||||
};
|
||||
|
||||
struct object::member
|
||||
struct ircd::json::object::member
|
||||
:std::pair<string_view, string_view>
|
||||
{
|
||||
member(const string_view &first = {}, const string_view &second = {})
|
||||
|
@ -132,7 +134,7 @@ struct object::member
|
|||
friend std::ostream &operator<<(std::ostream &, const object::member &);
|
||||
};
|
||||
|
||||
struct object::const_iterator
|
||||
struct ircd::json::object::const_iterator
|
||||
{
|
||||
using value_type = const member;
|
||||
using pointer = value_type *;
|
||||
|
@ -166,9 +168,6 @@ struct object::const_iterator
|
|||
friend bool operator>(const const_iterator &, const const_iterator &);
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::json::object::operator[](const path &path)
|
||||
const
|
||||
|
|
|
@ -22,16 +22,13 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_JSON_VALUE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace json {
|
||||
|
||||
// The ircd::json::value is used if we have to keep state in machine-form
|
||||
// rather than directly computing JSON strings. This class ends up being useful
|
||||
// for recursive initializer_lists to compose JSON from machine values. It
|
||||
// is lightweight, consuming the space of two pointers which is the same size
|
||||
// as a string_view.
|
||||
//
|
||||
struct value
|
||||
struct ircd::json::value
|
||||
{
|
||||
union // xxx std::variant
|
||||
{
|
||||
|
@ -59,8 +56,8 @@ struct value
|
|||
value(const string_view &sv, const enum type &);
|
||||
value(const string_view &sv);
|
||||
value(const char *const &s);
|
||||
value(const struct index *const &); // alloc = false
|
||||
value(std::unique_ptr<struct index>); // alloc = true
|
||||
value(const index *const &); // alloc = false
|
||||
value(std::unique_ptr<index>); // alloc = true
|
||||
value();
|
||||
value(value &&) noexcept;
|
||||
value(const value &) = delete;
|
||||
|
@ -77,17 +74,18 @@ struct value
|
|||
friend bool operator>(const value &a, const value &b);
|
||||
friend std::ostream &operator<<(std::ostream &, const value &);
|
||||
};
|
||||
template<> value::value(const double &floating);
|
||||
template<> value::value(const int64_t &integer);
|
||||
template<> value::value(const float &floating);
|
||||
template<> value::value(const int32_t &integer);
|
||||
template<> value::value(const int16_t &integer);
|
||||
template<> value::value(const std::string &str);
|
||||
|
||||
static_assert(sizeof(value) == 16, "");
|
||||
namespace ircd::json
|
||||
{
|
||||
template<> value::value(const double &floating);
|
||||
template<> value::value(const int64_t &integer);
|
||||
template<> value::value(const float &floating);
|
||||
template<> value::value(const int32_t &integer);
|
||||
template<> value::value(const int16_t &integer);
|
||||
template<> value::value(const std::string &str);
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace ircd
|
||||
static_assert(sizeof(ircd::json::value) == 16, "");
|
||||
|
||||
inline
|
||||
ircd::json::value::value()
|
||||
|
@ -111,7 +109,7 @@ ircd::json::value::value(const string_view &sv,
|
|||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(const struct index *const &object)
|
||||
ircd::json::value::value(const index *const &object)
|
||||
:object{object}
|
||||
,len{0}
|
||||
,type{OBJECT}
|
||||
|
@ -121,7 +119,7 @@ ircd::json::value::value(const struct index *const &object)
|
|||
{}
|
||||
|
||||
inline
|
||||
ircd::json::value::value(std::unique_ptr<struct index> object)
|
||||
ircd::json::value::value(std::unique_ptr<index> object)
|
||||
:object{object.get()}
|
||||
,len{0}
|
||||
,type{OBJECT}
|
||||
|
|
|
@ -23,171 +23,170 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_LEXICAL_H
|
||||
|
||||
namespace ircd {
|
||||
|
||||
//
|
||||
// Lexical conversions
|
||||
//
|
||||
IRCD_EXCEPTION(ircd::error, bad_lex_cast)
|
||||
namespace ircd
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, bad_lex_cast)
|
||||
|
||||
template<class T> bool try_lex_cast(const string_view &);
|
||||
template<> bool try_lex_cast<std::string>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<std::string_view>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<string_view>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<long double>(const string_view &);
|
||||
template<> bool try_lex_cast<double>(const string_view &);
|
||||
template<> bool try_lex_cast<ulong>(const string_view &);
|
||||
template<> bool try_lex_cast<long>(const string_view &);
|
||||
template<> bool try_lex_cast<uint>(const string_view &);
|
||||
template<> bool try_lex_cast<int>(const string_view &);
|
||||
template<> bool try_lex_cast<ushort>(const string_view &);
|
||||
template<> bool try_lex_cast<short>(const string_view &);
|
||||
template<> bool try_lex_cast<uint8_t>(const string_view &);
|
||||
template<> bool try_lex_cast<int8_t>(const string_view &);
|
||||
template<> bool try_lex_cast<bool>(const string_view &);
|
||||
template<class T> bool try_lex_cast(const string_view &);
|
||||
template<> bool try_lex_cast<std::string>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<std::string_view>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<string_view>(const string_view &); // stub always true
|
||||
template<> bool try_lex_cast<long double>(const string_view &);
|
||||
template<> bool try_lex_cast<double>(const string_view &);
|
||||
template<> bool try_lex_cast<ulong>(const string_view &);
|
||||
template<> bool try_lex_cast<long>(const string_view &);
|
||||
template<> bool try_lex_cast<uint>(const string_view &);
|
||||
template<> bool try_lex_cast<int>(const string_view &);
|
||||
template<> bool try_lex_cast<ushort>(const string_view &);
|
||||
template<> bool try_lex_cast<short>(const string_view &);
|
||||
template<> bool try_lex_cast<uint8_t>(const string_view &);
|
||||
template<> bool try_lex_cast<int8_t>(const string_view &);
|
||||
template<> bool try_lex_cast<bool>(const string_view &);
|
||||
|
||||
template<class T> T lex_cast(std::string &);
|
||||
template<class T> T lex_cast(const std::string &);
|
||||
template<class T> T lex_cast(const std::string_view &);
|
||||
template<class T> T lex_cast(const string_view &);
|
||||
template<> std::string &lex_cast(std::string &); // trivial
|
||||
template<> std::string lex_cast(const std::string &); // trivial
|
||||
template<> std::string_view lex_cast(const std::string_view &); // trivial
|
||||
template<> std::string lex_cast(const string_view &); // trivial
|
||||
template<> long double lex_cast(const string_view &);
|
||||
template<> double lex_cast(const string_view &);
|
||||
template<> ulong lex_cast(const string_view &);
|
||||
template<> long lex_cast(const string_view &);
|
||||
template<> uint lex_cast(const string_view &);
|
||||
template<> int lex_cast(const string_view &);
|
||||
template<> ushort lex_cast(const string_view &);
|
||||
template<> short lex_cast(const string_view &);
|
||||
template<> uint8_t lex_cast(const string_view &);
|
||||
template<> int8_t lex_cast(const string_view &);
|
||||
template<> bool lex_cast(const string_view &);
|
||||
template<class T> T lex_cast(std::string &);
|
||||
template<class T> T lex_cast(const std::string &);
|
||||
template<class T> T lex_cast(const std::string_view &);
|
||||
template<class T> T lex_cast(const string_view &);
|
||||
template<> std::string &lex_cast(std::string &); // trivial
|
||||
template<> std::string lex_cast(const std::string &); // trivial
|
||||
template<> std::string_view lex_cast(const std::string_view &); // trivial
|
||||
template<> std::string lex_cast(const string_view &); // trivial
|
||||
template<> long double lex_cast(const string_view &);
|
||||
template<> double lex_cast(const string_view &);
|
||||
template<> ulong lex_cast(const string_view &);
|
||||
template<> long lex_cast(const string_view &);
|
||||
template<> uint lex_cast(const string_view &);
|
||||
template<> int lex_cast(const string_view &);
|
||||
template<> ushort lex_cast(const string_view &);
|
||||
template<> short lex_cast(const string_view &);
|
||||
template<> uint8_t lex_cast(const string_view &);
|
||||
template<> int8_t lex_cast(const string_view &);
|
||||
template<> bool lex_cast(const string_view &);
|
||||
|
||||
// User supplied destination buffer
|
||||
template<class T> string_view lex_cast(T, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const std::string &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const std::string_view &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const string_view &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(long double, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(double, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(ulong, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(long, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(uint, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(int, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(ushort, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(short, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(uint8_t, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(int8_t, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(bool, char *const &buf, const size_t &max);
|
||||
// User supplied destination buffer
|
||||
template<class T> string_view lex_cast(T, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const std::string &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const std::string_view &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(const string_view &, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(long double, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(double, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(ulong, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(long, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(uint, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(int, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(ushort, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(short, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(uint8_t, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(int8_t, char *const &buf, const size_t &max);
|
||||
template<> string_view lex_cast(bool, char *const &buf, const size_t &max);
|
||||
|
||||
// Circular static thread_local buffer
|
||||
const size_t LEX_CAST_BUFS {256}; // plenty
|
||||
template<class T> string_view lex_cast(const T &t);
|
||||
// Circular static thread_local buffer
|
||||
const size_t LEX_CAST_BUFS {256}; // plenty
|
||||
template<class T> string_view lex_cast(const T &t);
|
||||
|
||||
//
|
||||
// String tokenization.
|
||||
//
|
||||
//
|
||||
// String tokenization.
|
||||
//
|
||||
|
||||
// Use the closure for best performance. Note that string_view's
|
||||
// are not required to be null terminated. Construct an std::string from the view to allocate
|
||||
// and copy the token with null termination.
|
||||
using token_view = std::function<void (const string_view &)>;
|
||||
void tokens(const string_view &str, const char *const &sep, const token_view &);
|
||||
size_t tokens(const string_view &str, const char *const &sep, const size_t &limit, const token_view &);
|
||||
// Use the closure for best performance. Note that string_view's
|
||||
// are not required to be null terminated. Construct an std::string from the view to allocate
|
||||
// and copy the token with null termination.
|
||||
using token_view = std::function<void (const string_view &)>;
|
||||
void tokens(const string_view &str, const char *const &sep, const token_view &);
|
||||
size_t tokens(const string_view &str, const char *const &sep, const size_t &limit, const token_view &);
|
||||
|
||||
// Copies tokens into your buffer and null terminates strtok() style. Returns BYTES of buf consumed.
|
||||
size_t tokens(const string_view &str, const char *const &sep, char *const &buf, const size_t &max, const token_view &);
|
||||
// Copies tokens into your buffer and null terminates strtok() style. Returns BYTES of buf consumed.
|
||||
size_t tokens(const string_view &str, const char *const &sep, char *const &buf, const size_t &max, const token_view &);
|
||||
|
||||
// Receive token view into iterator range
|
||||
template<class it> it tokens(const string_view &str, const char *const &sep, const it &b, const it &e);
|
||||
// Receive token view into iterator range
|
||||
template<class it> it tokens(const string_view &str, const char *const &sep, const it &b, const it &e);
|
||||
|
||||
// Receive token view into array
|
||||
template<size_t N> size_t tokens(const string_view &str, const char *const &sep, string_view (&buf)[N]);
|
||||
template<size_t N> size_t tokens(const string_view &str, const char *const &sep, std::array<string_view, N> &);
|
||||
// Receive token view into array
|
||||
template<size_t N> size_t tokens(const string_view &str, const char *const &sep, string_view (&buf)[N]);
|
||||
template<size_t N> size_t tokens(const string_view &str, const char *const &sep, std::array<string_view, N> &);
|
||||
|
||||
// Receive token view into new container (custom allocator)
|
||||
template<template<class, class>
|
||||
class C = std::vector,
|
||||
class T = string_view,
|
||||
class A>
|
||||
C<T, A> tokens(A allocator, const string_view &str, const char *const &sep);
|
||||
// Receive token view into new container (custom allocator)
|
||||
template<template<class, class>
|
||||
class C = std::vector,
|
||||
class T = string_view,
|
||||
class A>
|
||||
C<T, A> tokens(A allocator, const string_view &str, const char *const &sep);
|
||||
|
||||
// Receive token view into new container
|
||||
template<template<class, class>
|
||||
class C = std::vector,
|
||||
class T = string_view,
|
||||
class A = std::allocator<T>>
|
||||
C<T, A> tokens(const string_view &str, const char *const &sep);
|
||||
// Receive token view into new container
|
||||
template<template<class, class>
|
||||
class C = std::vector,
|
||||
class T = string_view,
|
||||
class A = std::allocator<T>>
|
||||
C<T, A> tokens(const string_view &str, const char *const &sep);
|
||||
|
||||
// Receive token view into new associative container (custom allocator)
|
||||
template<template<class, class, class>
|
||||
class C,
|
||||
class T = string_view,
|
||||
class Comp = std::less<T>,
|
||||
class A>
|
||||
C<T, Comp, A> tokens(A allocator, const string_view &str, const char *const &sep);
|
||||
// Receive token view into new associative container (custom allocator)
|
||||
template<template<class, class, class>
|
||||
class C,
|
||||
class T = string_view,
|
||||
class Comp = std::less<T>,
|
||||
class A>
|
||||
C<T, Comp, A> tokens(A allocator, const string_view &str, const char *const &sep);
|
||||
|
||||
// Receive token view into new associative container
|
||||
template<template<class, class, class>
|
||||
class C,
|
||||
class T = string_view,
|
||||
class Comp = std::less<T>,
|
||||
class A = std::allocator<T>>
|
||||
C<T, Comp, A> tokens(const string_view &str, const char *const &sep);
|
||||
// Receive token view into new associative container
|
||||
template<template<class, class, class>
|
||||
class C,
|
||||
class T = string_view,
|
||||
class Comp = std::less<T>,
|
||||
class A = std::allocator<T>>
|
||||
C<T, Comp, A> tokens(const string_view &str, const char *const &sep);
|
||||
|
||||
// Convenience to get individual tokens
|
||||
size_t tokens_count(const string_view &str, const char *const &sep);
|
||||
string_view token(const string_view &str, const char *const &sep, const size_t &at);
|
||||
string_view token_last(const string_view &str, const char *const &sep);
|
||||
string_view token_first(const string_view &str, const char *const &sep);
|
||||
string_view tokens_after(const string_view &str, const char *const &sep, const size_t &at);
|
||||
// Convenience to get individual tokens
|
||||
size_t tokens_count(const string_view &str, const char *const &sep);
|
||||
string_view token(const string_view &str, const char *const &sep, const size_t &at);
|
||||
string_view token_last(const string_view &str, const char *const &sep);
|
||||
string_view token_first(const string_view &str, const char *const &sep);
|
||||
string_view tokens_after(const string_view &str, const char *const &sep, const size_t &at);
|
||||
|
||||
//
|
||||
// Misc utils
|
||||
//
|
||||
//
|
||||
// Misc utils
|
||||
//
|
||||
|
||||
// Simple case insensitive comparison convenience utils
|
||||
struct iless;
|
||||
struct igreater;
|
||||
struct iequals;
|
||||
// Simple case insensitive comparison convenience utils
|
||||
struct iless;
|
||||
struct igreater;
|
||||
struct iequals;
|
||||
|
||||
// Vintage
|
||||
size_t strlcpy(char *const &dest, const char *const &src, const size_t &bufmax);
|
||||
size_t strlcat(char *const &dest, const char *const &src, const size_t &bufmax);
|
||||
// Vintage
|
||||
size_t strlcpy(char *const &dest, const char *const &src, const size_t &bufmax);
|
||||
size_t strlcat(char *const &dest, const char *const &src, const size_t &bufmax);
|
||||
|
||||
// Legacy
|
||||
char *strip_colour(char *string);
|
||||
char *strip_unprintable(char *string);
|
||||
char *reconstruct_parv(int parc, const char **parv);
|
||||
// Legacy
|
||||
char *strip_colour(char *string);
|
||||
char *strip_unprintable(char *string);
|
||||
char *reconstruct_parv(int parc, const char **parv);
|
||||
|
||||
char chop(string_view &str);
|
||||
size_t chomp(string_view &str, const char &c = '\n');
|
||||
size_t chomp(string_view &str, const string_view &c);
|
||||
template<class T, class delim> size_t chomp(iterators<T>, const delim &d);
|
||||
string_view rstrip(const string_view &str, const char &c = ' ');
|
||||
string_view rstrip(const string_view &str, const string_view &c);
|
||||
string_view lstrip(const string_view &str, const char &c = ' ');
|
||||
string_view lstrip(const string_view &str, const string_view &c);
|
||||
string_view strip(const string_view &str, const char &c = ' ');
|
||||
string_view strip(const string_view &str, const string_view &c);
|
||||
std::pair<string_view, string_view> split(const string_view &str, const char &delim = ' ');
|
||||
std::pair<string_view, string_view> split(const string_view &str, const string_view &delim);
|
||||
std::pair<string_view, string_view> rsplit(const string_view &str, const char &delim = ' ');
|
||||
std::pair<string_view, string_view> rsplit(const string_view &str, const string_view &delim);
|
||||
string_view between(const string_view &str, const string_view &a, const string_view &b);
|
||||
string_view between(const string_view &str, const char &a = '(', const char &b = ')');
|
||||
bool endswith(const string_view &str, const string_view &val);
|
||||
bool endswith(const string_view &str, const char &val);
|
||||
template<class It> bool endswith_any(const string_view &str, const It &begin, const It &end);
|
||||
bool startswith(const string_view &str, const string_view &val);
|
||||
bool startswith(const string_view &str, const char &val);
|
||||
string_view unquote(string_view str);
|
||||
std::string unquote(std::string &&);
|
||||
|
||||
} // namespace ircd
|
||||
char chop(string_view &str);
|
||||
size_t chomp(string_view &str, const char &c = '\n');
|
||||
size_t chomp(string_view &str, const string_view &c);
|
||||
template<class T, class delim> size_t chomp(iterators<T>, const delim &d);
|
||||
string_view rstrip(const string_view &str, const char &c = ' ');
|
||||
string_view rstrip(const string_view &str, const string_view &c);
|
||||
string_view lstrip(const string_view &str, const char &c = ' ');
|
||||
string_view lstrip(const string_view &str, const string_view &c);
|
||||
string_view strip(const string_view &str, const char &c = ' ');
|
||||
string_view strip(const string_view &str, const string_view &c);
|
||||
std::pair<string_view, string_view> split(const string_view &str, const char &delim = ' ');
|
||||
std::pair<string_view, string_view> split(const string_view &str, const string_view &delim);
|
||||
std::pair<string_view, string_view> rsplit(const string_view &str, const char &delim = ' ');
|
||||
std::pair<string_view, string_view> rsplit(const string_view &str, const string_view &delim);
|
||||
string_view between(const string_view &str, const string_view &a, const string_view &b);
|
||||
string_view between(const string_view &str, const char &a = '(', const char &b = ')');
|
||||
bool endswith(const string_view &str, const string_view &val);
|
||||
bool endswith(const string_view &str, const char &val);
|
||||
template<class It> bool endswith_any(const string_view &str, const It &begin, const It &end);
|
||||
bool startswith(const string_view &str, const string_view &val);
|
||||
bool startswith(const string_view &str, const char &val);
|
||||
string_view unquote(string_view str);
|
||||
std::string unquote(std::string &&);
|
||||
}
|
||||
|
||||
inline std::string
|
||||
ircd::unquote(std::string &&str)
|
||||
|
|
|
@ -31,30 +31,33 @@
|
|||
// without being destructed.
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
|
||||
// Tests if type inherits from std::enable_shared_from_this<>
|
||||
template<class T>
|
||||
constexpr typename std::enable_if<is_complete<T>::value, bool>::type
|
||||
is_shared_from_this()
|
||||
namespace ircd
|
||||
{
|
||||
return std::is_base_of<std::enable_shared_from_this<T>, T>();
|
||||
}
|
||||
// Tests if type inherits from std::enable_shared_from_this<>
|
||||
template<class T>
|
||||
constexpr typename std::enable_if<is_complete<T>::value, bool>::type
|
||||
is_shared_from_this()
|
||||
{
|
||||
return std::is_base_of<std::enable_shared_from_this<T>, T>();
|
||||
}
|
||||
|
||||
// Unconditional failure for fwd-declared incomplete types, which
|
||||
// obviously don't inherit from std::enable_shared_from_this<>
|
||||
template<class T>
|
||||
constexpr typename std::enable_if<!is_complete<T>::value, bool>::type
|
||||
is_shared_from_this()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Unconditional failure for fwd-declared incomplete types, which
|
||||
// obviously don't inherit from std::enable_shared_from_this<>
|
||||
template<class T>
|
||||
constexpr typename std::enable_if<!is_complete<T>::value, bool>::type
|
||||
is_shared_from_this()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convenience functions for types shared_from_this
|
||||
template<class T> std::shared_ptr<const T> shared_from(const T &t);
|
||||
template<class T> std::shared_ptr<T> shared_from(T &t);
|
||||
template<class T> std::weak_ptr<const T> weak_from(const T &t);
|
||||
template<class T> std::weak_ptr<T> weak_from(T &t);
|
||||
// Convenience functions for types shared_from_this
|
||||
template<class T> std::shared_ptr<const T> shared_from(const T &t);
|
||||
template<class T> std::shared_ptr<T> shared_from(T &t);
|
||||
template<class T> std::weak_ptr<const T> weak_from(const T &t);
|
||||
template<class T> std::weak_ptr<T> weak_from(T &t);
|
||||
|
||||
template<class T> struct life_guard;
|
||||
}
|
||||
|
||||
/* Use the life_guard to keep an object alive within a function running in a context.
|
||||
*
|
||||
|
@ -70,7 +73,7 @@ template<class T> std::weak_ptr<T> weak_from(T &t);
|
|||
}
|
||||
*/
|
||||
template<class T>
|
||||
struct life_guard
|
||||
struct ircd::life_guard
|
||||
:std::shared_ptr<T>
|
||||
{
|
||||
// This constructor is used when the templated type inherits from std::enable_shared_from_this<>
|
||||
|
@ -103,30 +106,28 @@ struct life_guard
|
|||
|
||||
template<class T>
|
||||
std::weak_ptr<T>
|
||||
weak_from(T &t)
|
||||
ircd::weak_from(T &t)
|
||||
{
|
||||
return shared_from(t);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::weak_ptr<const T>
|
||||
weak_from(const T &t)
|
||||
ircd::weak_from(const T &t)
|
||||
{
|
||||
return shared_from(t);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::shared_ptr<T>
|
||||
shared_from(T &t)
|
||||
ircd::shared_from(T &t)
|
||||
{
|
||||
return dynamic_pointer_cast<T>(t.shared_from_this());
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::shared_ptr<const T>
|
||||
shared_from(const T &t)
|
||||
ircd::shared_from(const T &t)
|
||||
{
|
||||
return dynamic_pointer_cast<const T>(t.shared_from_this());
|
||||
};
|
||||
|
||||
} // namespace ircd
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
struct listener;
|
||||
}
|
||||
|
||||
struct listener
|
||||
struct ircd::listener
|
||||
{
|
||||
struct acceptor;
|
||||
|
||||
|
@ -35,5 +38,3 @@ struct listener
|
|||
listener(const std::string &options);
|
||||
~listener() noexcept;
|
||||
};
|
||||
|
||||
} // namespace ircd
|
||||
|
|
|
@ -26,12 +26,9 @@
|
|||
// Utilities for internationalization.
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
namespace locale {
|
||||
|
||||
// On newer platforms (gcc-5 etc) these conversions are standard C++.
|
||||
// On older platforms the definition file may use boost::locale.
|
||||
namespace char16
|
||||
namespace ircd::locale::char16
|
||||
{
|
||||
char conv(const char16_t &);
|
||||
char16_t conv(const char &);
|
||||
|
@ -53,13 +50,15 @@ namespace char16
|
|||
std::ostream &operator<<(std::ostream &, const std::u16string &);
|
||||
}
|
||||
|
||||
using char16::operator<<;
|
||||
namespace ircd::locale
|
||||
{
|
||||
using char16::operator<<;
|
||||
}
|
||||
|
||||
} // namespace locale
|
||||
|
||||
using locale::operator<<;
|
||||
|
||||
} // namespace ircd
|
||||
namespace ircd
|
||||
{
|
||||
using locale::operator<<;
|
||||
}
|
||||
|
||||
inline std::ostream &
|
||||
ircd::locale::char16::operator<<(std::ostream &s,
|
||||
|
|
|
@ -34,21 +34,47 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_LOGGER_H
|
||||
|
||||
namespace ircd {
|
||||
|
||||
const char *smalldate(const time_t &);
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
// windows.h #define conflicts with our facility
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
namespace ircd {
|
||||
namespace log {
|
||||
namespace ircd
|
||||
{
|
||||
const char *smalldate(const time_t &);
|
||||
}
|
||||
|
||||
enum facility
|
||||
namespace ircd::log
|
||||
{
|
||||
enum facility :int;
|
||||
const char *reflect(const facility &);
|
||||
|
||||
struct log;
|
||||
struct console_quiet;
|
||||
|
||||
void slog(const facility &, const std::function<void (std::ostream &)> &);
|
||||
void vlog(const facility &, const std::string &name, const char *const &fmt, const va_rtti &ap);
|
||||
void vlog(const facility &, const char *const &fmt, const va_rtti &ap);
|
||||
void mark(const facility &, const char *const &msg = nullptr);
|
||||
void mark(const char *const &msg = nullptr);
|
||||
|
||||
template<class... args> void critical(const char *const &fmt, args&&...);
|
||||
template<class... args> void error(const char *const &fmt, args&&...);
|
||||
template<class... args> void warning(const char *const &fmt, args&&...);
|
||||
template<class... args> void notice(const char *const &fmt, args&&...);
|
||||
template<class... args> void info(const char *const &fmt, args&&...);
|
||||
template<class... args> void debug(const char *const &fmt, args&&...);
|
||||
|
||||
void flush();
|
||||
void close();
|
||||
void open();
|
||||
|
||||
void init();
|
||||
void fini();
|
||||
}
|
||||
|
||||
enum ircd::log::facility
|
||||
:int
|
||||
{
|
||||
CRITICAL = 0,
|
||||
ERROR = 1,
|
||||
|
@ -59,14 +85,7 @@ enum facility
|
|||
_NUM_
|
||||
};
|
||||
|
||||
const char *reflect(const facility &);
|
||||
void slog(const facility &, const std::function<void (std::ostream &)> &);
|
||||
void vlog(const facility &, const std::string &name, const char *const &fmt, const va_rtti &ap);
|
||||
void vlog(const facility &, const char *const &fmt, const va_rtti &ap);
|
||||
void mark(const facility &, const char *const &msg = nullptr);
|
||||
void mark(const char *const &msg = nullptr);
|
||||
|
||||
class log
|
||||
class ircd::log::log
|
||||
{
|
||||
std::string name;
|
||||
|
||||
|
@ -84,29 +103,12 @@ class log
|
|||
log(const std::string &name);
|
||||
};
|
||||
|
||||
template<class... args> void critical(const char *const &fmt, args&&...);
|
||||
template<class... args> void error(const char *const &fmt, args&&...);
|
||||
template<class... args> void warning(const char *const &fmt, args&&...);
|
||||
template<class... args> void notice(const char *const &fmt, args&&...);
|
||||
template<class... args> void info(const char *const &fmt, args&&...);
|
||||
template<class... args> void debug(const char *const &fmt, args&&...);
|
||||
|
||||
struct console_quiet
|
||||
struct ircd::log::console_quiet
|
||||
{
|
||||
console_quiet(const bool &showmsg = true);
|
||||
~console_quiet();
|
||||
};
|
||||
|
||||
void flush();
|
||||
void close();
|
||||
void open();
|
||||
|
||||
void init();
|
||||
void fini();
|
||||
|
||||
} // namespace log
|
||||
} // namespace ircd
|
||||
|
||||
template<class... args>
|
||||
void
|
||||
ircd::log::debug(const char *const &fmt,
|
||||
|
|
|
@ -22,27 +22,31 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_MAPI_H
|
||||
|
||||
namespace ircd {
|
||||
namespace mapi {
|
||||
|
||||
struct header;
|
||||
using magic_t = uint16_t;
|
||||
using version_t = uint16_t;
|
||||
using metadata = std::map<std::string, std::string>;
|
||||
using init_function = std::function<void ()>;
|
||||
using fini_function = std::function<void ()>;
|
||||
|
||||
const char *const header_symbol_name
|
||||
namespace ircd::mapi
|
||||
{
|
||||
"IRCD_MODULE"
|
||||
};
|
||||
struct header;
|
||||
using magic_t = uint16_t;
|
||||
using version_t = uint16_t;
|
||||
using metadata = std::map<std::string, std::string>;
|
||||
using init_function = std::function<void ()>;
|
||||
using fini_function = std::function<void ()>;
|
||||
|
||||
constexpr const magic_t MAGIC
|
||||
{
|
||||
0x4D41
|
||||
};
|
||||
const char *const header_symbol_name
|
||||
{
|
||||
"IRCD_MODULE"
|
||||
};
|
||||
|
||||
struct header
|
||||
constexpr const magic_t MAGIC
|
||||
{
|
||||
0x4D41
|
||||
};
|
||||
|
||||
// Used to communicate whether a module unload actually took place. dlclose() is allowed to return
|
||||
// success but the actual static destruction of the module's contents doesn't lie. (mods.cc)
|
||||
extern bool static_destruction;
|
||||
}
|
||||
|
||||
struct ircd::mapi::header
|
||||
{
|
||||
magic_t magic; // The magic must match MAGIC
|
||||
version_t version; // Version indicator
|
||||
|
@ -62,14 +66,10 @@ struct header
|
|||
~header() noexcept;
|
||||
};
|
||||
|
||||
// Used to communicate whether a module unload actually took place. dlclose() is allowed to return
|
||||
// success but the actual static destruction of the module's contents doesn't lie. (mods.cc)
|
||||
extern bool static_destruction;
|
||||
|
||||
inline
|
||||
header::header(const char *const &desc,
|
||||
init_function init,
|
||||
fini_function fini)
|
||||
ircd::mapi::header::header(const char *const &desc,
|
||||
init_function init,
|
||||
fini_function fini)
|
||||
:magic(MAGIC)
|
||||
,version(4)
|
||||
,timestamp(RB_DATECODE)
|
||||
|
@ -83,24 +83,21 @@ header::header(const char *const &desc,
|
|||
}
|
||||
|
||||
inline
|
||||
header::~header()
|
||||
ircd::mapi::header::~header()
|
||||
noexcept
|
||||
{
|
||||
static_destruction = true;
|
||||
}
|
||||
|
||||
inline auto &
|
||||
header::operator[](const std::string &key)
|
||||
ircd::mapi::header::operator[](const std::string &key)
|
||||
{
|
||||
return meta[key];
|
||||
}
|
||||
|
||||
inline auto &
|
||||
header::operator[](const std::string &key)
|
||||
ircd::mapi::header::operator[](const std::string &key)
|
||||
const
|
||||
{
|
||||
return meta.at(key);
|
||||
}
|
||||
|
||||
} // namespace mapi
|
||||
} // namespace ircd
|
||||
|
|
|
@ -22,16 +22,54 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_MODS_H
|
||||
|
||||
namespace ircd {
|
||||
namespace mods {
|
||||
namespace ircd::mods
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, filesystem_error)
|
||||
IRCD_EXCEPTION(error, invalid_export)
|
||||
IRCD_EXCEPTION(error, expired_symbol)
|
||||
IRCD_EXCEPTION(error, undefined_symbol)
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, filesystem_error)
|
||||
IRCD_EXCEPTION(error, invalid_export)
|
||||
IRCD_EXCEPTION(error, expired_symbol)
|
||||
IRCD_EXCEPTION(error, undefined_symbol)
|
||||
struct mod;
|
||||
struct module;
|
||||
struct sym_ptr;
|
||||
template<class T> struct import;
|
||||
template<class T> struct import_shared;
|
||||
struct paths extern paths;
|
||||
|
||||
struct paths
|
||||
std::string demangle(const std::string &symbol);
|
||||
std::string postfixed(const std::string &name);
|
||||
std::string unpostfixed(const std::string &name);
|
||||
|
||||
std::vector<std::string> symbols(const std::string &fullpath, const std::string §ion);
|
||||
std::vector<std::string> symbols(const std::string &fullpath);
|
||||
std::vector<std::string> sections(const std::string &fullpath);
|
||||
|
||||
// Find module names where symbol resides
|
||||
bool has_symbol(const std::string &name, const std::string &symbol);
|
||||
std::vector<std::string> find_symbol(const std::string &symbol);
|
||||
|
||||
// returns dir/name of first dir containing 'name' (and this will be a loadable module)
|
||||
// Unlike libltdl, the reason each individual candidate failed is presented in a vector.
|
||||
std::string search(const std::string &name, std::vector<std::string> &why);
|
||||
std::string search(const std::string &name);
|
||||
|
||||
// Potential modules available to load
|
||||
std::forward_list<std::string> available();
|
||||
bool available(const std::string &name);
|
||||
bool loaded(const std::string &name);
|
||||
}
|
||||
|
||||
// Bring struct module into main ircd::
|
||||
namespace ircd
|
||||
{
|
||||
using mods::module;
|
||||
using mods::import;
|
||||
using mods::import_shared;
|
||||
using mods::demangle;
|
||||
}
|
||||
|
||||
struct ircd::mods::paths
|
||||
:std::vector<std::string>
|
||||
{
|
||||
bool added(const std::string &dir) const;
|
||||
|
@ -41,11 +79,9 @@ struct paths
|
|||
bool add(const std::string &dir);
|
||||
|
||||
paths();
|
||||
}
|
||||
extern paths;
|
||||
};
|
||||
|
||||
struct mod;
|
||||
struct module
|
||||
struct ircd::mods::module
|
||||
:std::shared_ptr<mod>
|
||||
{
|
||||
std::string name() const;
|
||||
|
@ -67,10 +103,13 @@ struct module
|
|||
~module() noexcept;
|
||||
};
|
||||
|
||||
template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const;
|
||||
template<> uint8_t *module::ptr<uint8_t>(const std::string &name);
|
||||
namespace ircd::mods
|
||||
{
|
||||
template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const;
|
||||
template<> uint8_t *module::ptr<uint8_t>(const std::string &name);
|
||||
}
|
||||
|
||||
class sym_ptr
|
||||
class ircd::mods::sym_ptr
|
||||
:std::weak_ptr<mod>
|
||||
{
|
||||
void *ptr;
|
||||
|
@ -93,7 +132,7 @@ class sym_ptr
|
|||
};
|
||||
|
||||
template<class T>
|
||||
struct import
|
||||
struct ircd::mods::import
|
||||
:sym_ptr
|
||||
{
|
||||
template<class... args>
|
||||
|
@ -114,7 +153,7 @@ struct import
|
|||
};
|
||||
|
||||
template<class T>
|
||||
struct import_shared
|
||||
struct ircd::mods::import_shared
|
||||
:import<std::shared_ptr<T>>
|
||||
,std::shared_ptr<T>
|
||||
{
|
||||
|
@ -129,42 +168,6 @@ struct import_shared
|
|||
import_shared(const std::string &modname, const std::string &symname);
|
||||
};
|
||||
|
||||
|
||||
std::string demangle(const std::string &symbol);
|
||||
|
||||
std::string postfixed(const std::string &name);
|
||||
std::string unpostfixed(const std::string &name);
|
||||
|
||||
std::vector<std::string> symbols(const std::string &fullpath, const std::string §ion);
|
||||
std::vector<std::string> symbols(const std::string &fullpath);
|
||||
std::vector<std::string> sections(const std::string &fullpath);
|
||||
|
||||
// Find module names where symbol resides
|
||||
bool has_symbol(const std::string &name, const std::string &symbol);
|
||||
std::vector<std::string> find_symbol(const std::string &symbol);
|
||||
|
||||
// returns dir/name of first dir containing 'name' (and this will be a loadable module)
|
||||
// Unlike libltdl, the reason each individual candidate failed is presented in a vector.
|
||||
std::string search(const std::string &name, std::vector<std::string> &why);
|
||||
std::string search(const std::string &name);
|
||||
|
||||
// Potential modules available to load
|
||||
std::forward_list<std::string> available();
|
||||
bool available(const std::string &name);
|
||||
bool loaded(const std::string &name);
|
||||
|
||||
} // namespace mods
|
||||
} // namespace ircd
|
||||
|
||||
namespace ircd {
|
||||
|
||||
using mods::module; // Bring struct module into main ircd::
|
||||
using mods::import;
|
||||
using mods::import_shared;
|
||||
using mods::demangle;
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
template<class T>
|
||||
ircd::mods::import_shared<T>::import_shared(const std::string &modname,
|
||||
const std::string &symname)
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_PARAMS_H
|
||||
|
||||
namespace ircd {
|
||||
inline namespace util {
|
||||
namespace ircd::util
|
||||
{
|
||||
struct params;
|
||||
}
|
||||
|
||||
class params
|
||||
class ircd::util::params
|
||||
{
|
||||
string_view in;
|
||||
const char *sep;
|
||||
|
@ -49,9 +51,6 @@ class params
|
|||
const std::initializer_list<const char *> &names = {});
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
} // namespace ircd
|
||||
|
||||
inline
|
||||
ircd::util::params::params(const string_view &in,
|
||||
const char *const &sep,
|
||||
|
|
|
@ -25,9 +25,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_PARSE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
struct parse;
|
||||
}
|
||||
|
||||
struct parse
|
||||
struct ircd::parse
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
IRCD_EXCEPTION(error, grammar_error)
|
||||
|
@ -41,7 +44,7 @@ struct parse
|
|||
struct buffer;
|
||||
};
|
||||
|
||||
struct parse::grammar
|
||||
struct ircd::parse::grammar
|
||||
{
|
||||
static std::map<std::string_view, const grammar *> grammars;
|
||||
|
||||
|
@ -55,7 +58,7 @@ struct parse::grammar
|
|||
~grammar() noexcept;
|
||||
};
|
||||
|
||||
struct parse::buffer
|
||||
struct ircd::parse::buffer
|
||||
{
|
||||
char *base; // Lowest address of the buffer (const)
|
||||
const char *parsed; // Data between [base, parsed] is completed
|
||||
|
@ -95,7 +98,7 @@ struct parse::buffer
|
|||
{}
|
||||
};
|
||||
|
||||
struct parse::capstan
|
||||
struct ircd::parse::capstan
|
||||
{
|
||||
const char *&parsed;
|
||||
char *&read;
|
||||
|
@ -111,8 +114,6 @@ struct parse::capstan
|
|||
capstan(buffer &, const decltype(reader) &reader = nullptr);
|
||||
};
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
inline
|
||||
ircd::parse::capstan::capstan(buffer &buffer,
|
||||
const decltype(reader) &reader)
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_UTIL_RANDOM_H
|
||||
|
||||
namespace ircd {
|
||||
namespace rand {
|
||||
namespace ircd::rand
|
||||
{
|
||||
extern std::random_device device;
|
||||
extern std::mt19937_64 mt;
|
||||
}
|
||||
|
||||
extern std::random_device device;
|
||||
extern std::mt19937_64 mt;
|
||||
|
||||
namespace dict
|
||||
namespace ircd::rand::dict
|
||||
{
|
||||
extern const std::string alnum;
|
||||
extern const std::string alpha;
|
||||
|
@ -38,20 +38,20 @@ namespace dict
|
|||
extern const std::string numeric;
|
||||
}
|
||||
|
||||
uint64_t integer();
|
||||
uint64_t integer(const uint64_t &min, const uint64_t &max);
|
||||
namespace ircd::rand
|
||||
{
|
||||
uint64_t integer();
|
||||
uint64_t integer(const uint64_t &min, const uint64_t &max);
|
||||
|
||||
// Random character from dictionary
|
||||
char character(const std::string &dict = dict::alnum);
|
||||
// Random character from dictionary
|
||||
char character(const std::string &dict = dict::alnum);
|
||||
|
||||
// Random string of len from dictionary; char buffers null terminated, uchar not.
|
||||
template<size_t size> string_view string(const std::string &dict, const size_t &len, char (&buf)[size]);
|
||||
string_view string(const std::string &dict, const size_t &len, char *const &buf, const size_t &max);
|
||||
string_view string(const std::string &dict, const size_t &len, uint8_t *const &buf);
|
||||
std::string string(const std::string &dict, const size_t &len);
|
||||
|
||||
} // namespace rand
|
||||
} // namespace ircd
|
||||
// Random string of len from dictionary; char buffers null terminated, uchar not.
|
||||
template<size_t size> string_view string(const std::string &dict, const size_t &len, char (&buf)[size]);
|
||||
string_view string(const std::string &dict, const size_t &len, char *const &buf, const size_t &max);
|
||||
string_view string(const std::string &dict, const size_t &len, uint8_t *const &buf);
|
||||
std::string string(const std::string &dict, const size_t &len);
|
||||
}
|
||||
|
||||
template<size_t size>
|
||||
ircd::string_view
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_RESOURCE_H
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
struct resource;
|
||||
}
|
||||
|
||||
struct resource
|
||||
struct ircd::resource
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
|
||||
|
@ -67,9 +70,11 @@ struct resource
|
|||
static resource &find(string_view path);
|
||||
};
|
||||
|
||||
struct resource::request
|
||||
struct ircd::resource::request
|
||||
:json::object
|
||||
{
|
||||
template<class> struct body;
|
||||
|
||||
const http::request::head &head;
|
||||
http::request::content &content;
|
||||
http::query::string query;
|
||||
|
@ -77,7 +82,14 @@ struct resource::request
|
|||
request(const http::request::head &head, http::request::content &content, http::query::string query);
|
||||
};
|
||||
|
||||
struct resource::response
|
||||
template<class tuple>
|
||||
struct ircd::resource::request::body
|
||||
:tuple
|
||||
{
|
||||
body(const resource::request &);
|
||||
};
|
||||
|
||||
struct ircd::resource::response
|
||||
{
|
||||
response(client &, const string_view &str, const string_view &ct = "text/plain; charset=utf8", const http::code & = http::OK);
|
||||
response(client &, const json::object & = "{}", const http::code & = http::OK);
|
||||
|
@ -86,7 +98,7 @@ struct resource::response
|
|||
response() = default;
|
||||
};
|
||||
|
||||
struct resource::method
|
||||
struct ircd::resource::method
|
||||
{
|
||||
enum flag
|
||||
{
|
||||
|
@ -114,4 +126,8 @@ struct resource::method
|
|||
virtual ~method() noexcept;
|
||||
};
|
||||
|
||||
} // namespace ircd
|
||||
template<class tuple>
|
||||
ircd::resource::request::body<tuple>::body(const resource::request &request)
|
||||
:tuple{request}
|
||||
{
|
||||
}
|
||||
|
|
|
@ -27,29 +27,37 @@
|
|||
#include <boost/asio/steady_timer.hpp>
|
||||
#include "ctx/continuation.h"
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
namespace asio = boost::asio;
|
||||
namespace ip = asio::ip;
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace ip = asio::ip;
|
||||
using boost::system::error_code;
|
||||
using asio::steady_timer;
|
||||
|
||||
using boost::system::error_code;
|
||||
using asio::steady_timer;
|
||||
IRCD_EXCEPTION(error, nxdomain)
|
||||
|
||||
IRCD_EXCEPTION(error, nxdomain)
|
||||
struct socket;
|
||||
|
||||
extern asio::ssl::context sslv23_client;
|
||||
extern asio::ssl::context sslv23_client;
|
||||
|
||||
std::string string(const ip::address &);
|
||||
ip::address address(const ip::tcp::endpoint &);
|
||||
std::string hostaddr(const ip::tcp::endpoint &);
|
||||
uint16_t port(const ip::tcp::endpoint &);
|
||||
std::string string(const ip::address &);
|
||||
ip::address address(const ip::tcp::endpoint &);
|
||||
std::string hostaddr(const ip::tcp::endpoint &);
|
||||
uint16_t port(const ip::tcp::endpoint &);
|
||||
|
||||
} // namespace ircd
|
||||
template<class iov> size_t write(socket &, const iov &); // write_all
|
||||
template<class iov> size_t write(socket &, iov &); // write_some
|
||||
size_t write(socket &, const char *const &buf, const size_t &size);
|
||||
size_t write(socket &, const string_view &);
|
||||
|
||||
namespace ircd {
|
||||
template<class iov> size_t read(socket &, const iov &); // read_all
|
||||
template<class iov> size_t read(socket &, iov &); // read_some
|
||||
size_t read(socket &, char *const &buf, const size_t &max);
|
||||
}
|
||||
|
||||
struct socket
|
||||
:std::enable_shared_from_this<socket>
|
||||
struct ircd::socket
|
||||
:std::enable_shared_from_this<ircd::socket>
|
||||
{
|
||||
struct init;
|
||||
struct stat;
|
||||
|
@ -137,7 +145,7 @@ struct socket
|
|||
~socket() noexcept;
|
||||
};
|
||||
|
||||
class socket::scope_timeout
|
||||
class ircd::socket::scope_timeout
|
||||
{
|
||||
socket *s;
|
||||
|
||||
|
@ -149,7 +157,7 @@ class socket::scope_timeout
|
|||
~scope_timeout() noexcept;
|
||||
};
|
||||
|
||||
class socket::io
|
||||
class ircd::socket::io
|
||||
{
|
||||
struct socket &sock;
|
||||
struct stat &stat;
|
||||
|
@ -161,26 +169,16 @@ class socket::io
|
|||
io(struct socket &, struct stat &, const std::function<size_t ()> &closure);
|
||||
};
|
||||
|
||||
struct socket::init
|
||||
struct ircd::socket::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
template<class iov> size_t write(socket &, const iov &); // write_all
|
||||
template<class iov> size_t write(socket &, iov &); // write_some
|
||||
size_t write(socket &, const char *const &buf, const size_t &size);
|
||||
size_t write(socket &, const string_view &);
|
||||
|
||||
template<class iov> size_t read(socket &, const iov &); // read_all
|
||||
template<class iov> size_t read(socket &, iov &); // read_some
|
||||
size_t read(socket &, char *const &buf, const size_t &max);
|
||||
|
||||
|
||||
template<class iov>
|
||||
size_t
|
||||
read(socket &socket,
|
||||
iov &bufs)
|
||||
ircd::read(socket &socket,
|
||||
iov &bufs)
|
||||
{
|
||||
const auto read(socket.read_some(bufs));
|
||||
const auto consumed(consume(bufs, read));
|
||||
|
@ -190,16 +188,16 @@ read(socket &socket,
|
|||
|
||||
template<class iov>
|
||||
size_t
|
||||
read(socket &socket,
|
||||
const iov &bufs)
|
||||
ircd::read(socket &socket,
|
||||
const iov &bufs)
|
||||
{
|
||||
return socket.read(bufs);
|
||||
}
|
||||
|
||||
template<class iov>
|
||||
size_t
|
||||
write(socket &socket,
|
||||
iov &bufs)
|
||||
ircd::write(socket &socket,
|
||||
iov &bufs)
|
||||
{
|
||||
const auto wrote(socket.write_some(bufs));
|
||||
const auto consumed(consume(bufs, wrote));
|
||||
|
@ -209,8 +207,8 @@ write(socket &socket,
|
|||
|
||||
template<class iov>
|
||||
size_t
|
||||
write(socket &socket,
|
||||
const iov &bufs)
|
||||
ircd::write(socket &socket,
|
||||
const iov &bufs)
|
||||
{
|
||||
const auto wrote(socket.write(bufs));
|
||||
assert(wrote == size(bufs));
|
||||
|
@ -218,9 +216,9 @@ write(socket &socket,
|
|||
}
|
||||
|
||||
inline
|
||||
socket::io::io(struct socket &sock,
|
||||
struct stat &stat,
|
||||
const std::function<size_t ()> &closure)
|
||||
ircd::socket::io::io(struct socket &sock,
|
||||
struct stat &stat,
|
||||
const std::function<size_t ()> &closure)
|
||||
:sock{sock}
|
||||
,stat{stat}
|
||||
,bytes{closure()}
|
||||
|
@ -230,7 +228,7 @@ socket::io::io(struct socket &sock,
|
|||
}
|
||||
|
||||
inline
|
||||
socket::io::operator size_t()
|
||||
ircd::socket::io::operator size_t()
|
||||
const
|
||||
{
|
||||
return bytes;
|
||||
|
@ -238,7 +236,7 @@ const
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::write(const iov &bufs)
|
||||
ircd::socket::write(const iov &bufs)
|
||||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
|
@ -248,8 +246,8 @@ socket::write(const iov &bufs)
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::write(const iov &bufs,
|
||||
error_code &ec)
|
||||
ircd::socket::write(const iov &bufs,
|
||||
error_code &ec)
|
||||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
|
@ -259,7 +257,7 @@ socket::write(const iov &bufs,
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::write_some(const iov &bufs)
|
||||
ircd::socket::write_some(const iov &bufs)
|
||||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
|
@ -269,8 +267,8 @@ socket::write_some(const iov &bufs)
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::write_some(const iov &bufs,
|
||||
error_code &ec)
|
||||
ircd::socket::write_some(const iov &bufs,
|
||||
error_code &ec)
|
||||
{
|
||||
return io(*this, out, [&]
|
||||
{
|
||||
|
@ -280,7 +278,7 @@ socket::write_some(const iov &bufs,
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::read(const iov &bufs)
|
||||
ircd::socket::read(const iov &bufs)
|
||||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
|
@ -295,8 +293,8 @@ socket::read(const iov &bufs)
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::read(const iov &bufs,
|
||||
error_code &ec)
|
||||
ircd::socket::read(const iov &bufs,
|
||||
error_code &ec)
|
||||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
|
@ -306,7 +304,7 @@ socket::read(const iov &bufs,
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::read_some(const iov &bufs)
|
||||
ircd::socket::read_some(const iov &bufs)
|
||||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
|
@ -321,8 +319,8 @@ socket::read_some(const iov &bufs)
|
|||
|
||||
template<class iov>
|
||||
auto
|
||||
socket::read_some(const iov &bufs,
|
||||
error_code &ec)
|
||||
ircd::socket::read_some(const iov &bufs,
|
||||
error_code &ec)
|
||||
{
|
||||
return io(*this, in, [&]
|
||||
{
|
||||
|
@ -332,7 +330,7 @@ socket::read_some(const iov &bufs,
|
|||
|
||||
template<class duration>
|
||||
void
|
||||
socket::set_timeout(const duration &t)
|
||||
ircd::socket::set_timeout(const duration &t)
|
||||
{
|
||||
if(t < duration(0))
|
||||
return;
|
||||
|
@ -343,8 +341,8 @@ socket::set_timeout(const duration &t)
|
|||
|
||||
template<class duration>
|
||||
void
|
||||
socket::set_timeout(const duration &t,
|
||||
handler h)
|
||||
ircd::socket::set_timeout(const duration &t,
|
||||
handler h)
|
||||
{
|
||||
if(t < duration(0))
|
||||
return;
|
||||
|
@ -353,8 +351,6 @@ socket::set_timeout(const duration &t,
|
|||
timer.async_wait(std::move(h));
|
||||
}
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
inline uint16_t
|
||||
ircd::port(const ip::tcp::endpoint &ep)
|
||||
{
|
||||
|
|
|
@ -132,11 +132,10 @@ extern "C" {
|
|||
#define AFGP(a, b) __attribute__((format(gnu_printf, a, b)))
|
||||
|
||||
// Experimental std::string_view
|
||||
namespace std {
|
||||
|
||||
using experimental::string_view;
|
||||
|
||||
} // namespace std
|
||||
namespace std
|
||||
{
|
||||
using experimental::string_view;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -145,42 +144,38 @@ using experimental::string_view;
|
|||
|
||||
// Boost is not exposed unless explicitly included by a definition file. This
|
||||
// is a major improvement of project compile time.
|
||||
namespace boost {
|
||||
namespace 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
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
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
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Items imported into our namespace.
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
|
||||
using std::nullptr_t;
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using std::get;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::microseconds;
|
||||
using std::chrono::nanoseconds;
|
||||
using std::chrono::duration_cast;
|
||||
using std::static_pointer_cast;
|
||||
using std::dynamic_pointer_cast;
|
||||
using std::const_pointer_cast;
|
||||
using ostream = std::ostream;
|
||||
namespace ph = std::placeholders;
|
||||
namespace asio = boost::asio;
|
||||
using namespace std::string_literals;
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
} // namespace ircd
|
||||
namespace ircd
|
||||
{
|
||||
using std::nullptr_t;
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using std::get;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::microseconds;
|
||||
using std::chrono::nanoseconds;
|
||||
using std::chrono::duration_cast;
|
||||
using std::static_pointer_cast;
|
||||
using std::dynamic_pointer_cast;
|
||||
using std::const_pointer_cast;
|
||||
using ostream = std::ostream;
|
||||
namespace ph = std::placeholders;
|
||||
namespace asio = boost::asio;
|
||||
using namespace std::string_literals;
|
||||
using namespace std::literals::chrono_literals;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -188,15 +183,14 @@ using namespace std::literals::chrono_literals;
|
|||
//
|
||||
|
||||
// Unsorted section
|
||||
namespace ircd {
|
||||
namespace ircd
|
||||
{
|
||||
extern boost::asio::io_service *ios;
|
||||
constexpr size_t BUFSIZE { 512 };
|
||||
|
||||
extern boost::asio::io_service *ios;
|
||||
constexpr size_t BUFSIZE { 512 };
|
||||
|
||||
struct socket;
|
||||
struct client;
|
||||
|
||||
} // namespace ircd
|
||||
struct socket;
|
||||
struct client;
|
||||
}
|
||||
|
||||
#include "util.h"
|
||||
#include "rand.h"
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_UTIL_TIMER_H
|
||||
|
||||
namespace ircd {
|
||||
inline namespace util {
|
||||
namespace ircd::util
|
||||
{
|
||||
struct timer;
|
||||
}
|
||||
|
||||
struct timer
|
||||
struct ircd::util::timer
|
||||
{
|
||||
using clock = std::chrono::steady_clock;
|
||||
|
||||
|
@ -42,14 +44,14 @@ struct timer
|
|||
};
|
||||
|
||||
inline
|
||||
timer::timer()
|
||||
ircd::util::timer::timer()
|
||||
:accumulator{0ns}
|
||||
,start{clock::now()}
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
timer::timer(const std::function<void ()> &func)
|
||||
ircd::util::timer::timer(const std::function<void ()> &func)
|
||||
:timer{}
|
||||
{
|
||||
func();
|
||||
|
@ -57,7 +59,7 @@ timer::timer(const std::function<void ()> &func)
|
|||
}
|
||||
|
||||
inline void
|
||||
timer::stop()
|
||||
ircd::util::timer::stop()
|
||||
{
|
||||
const auto now(clock::now());
|
||||
if(start == clock::time_point::min())
|
||||
|
@ -68,7 +70,7 @@ timer::stop()
|
|||
}
|
||||
|
||||
inline void
|
||||
timer::cont()
|
||||
ircd::util::timer::cont()
|
||||
{
|
||||
if(start != clock::time_point::min())
|
||||
{
|
||||
|
@ -81,11 +83,8 @@ timer::cont()
|
|||
|
||||
template<class duration>
|
||||
duration
|
||||
timer::get()
|
||||
ircd::util::timer::get()
|
||||
const
|
||||
{
|
||||
return std::chrono::duration_cast<duration>(accumulator);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace ircd
|
||||
|
|
72
ircd/ctx.cc
72
ircd/ctx.cc
|
@ -27,10 +27,7 @@
|
|||
// (internal)
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
|
||||
struct ctx
|
||||
struct ircd::ctx::ctx
|
||||
{
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
|
@ -70,9 +67,6 @@ struct ctx
|
|||
ctx(const ctx &) = delete;
|
||||
};
|
||||
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
||||
decltype(ircd::ctx::ctx::id_ctr)
|
||||
ircd::ctx::ctx::id_ctr
|
||||
{
|
||||
|
@ -619,11 +613,22 @@ catch(const std::exception &e)
|
|||
// ctx_prof.h
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace prof {
|
||||
namespace ircd::ctx::prof
|
||||
{
|
||||
time_point cur_slice_start; // Time slice state
|
||||
|
||||
struct settings settings
|
||||
size_t stack_usage_here(const ctx &) __attribute__((noinline));
|
||||
void check_stack();
|
||||
void check_slice();
|
||||
void slice_start();
|
||||
|
||||
void handle_cur_continue();
|
||||
void handle_cur_yield();
|
||||
void handle_cur_leave();
|
||||
void handle_cur_enter();
|
||||
}
|
||||
|
||||
struct ircd::ctx::prof::settings ircd::ctx::prof::settings
|
||||
{
|
||||
0.46, // stack_usage_warning
|
||||
0.67, // stack_usage_assertion
|
||||
|
@ -633,22 +638,6 @@ struct settings settings
|
|||
0us, // slice_assertion
|
||||
};
|
||||
|
||||
time_point cur_slice_start; // Time slice state
|
||||
|
||||
size_t stack_usage_here(const ctx &) __attribute__((noinline));
|
||||
void check_stack();
|
||||
void check_slice();
|
||||
void slice_start();
|
||||
|
||||
void handle_cur_continue();
|
||||
void handle_cur_yield();
|
||||
void handle_cur_leave();
|
||||
void handle_cur_enter();
|
||||
|
||||
} // namespace prof
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
|
||||
void
|
||||
ircd::ctx::prof::mark(const event &e)
|
||||
{
|
||||
|
@ -747,25 +736,20 @@ ircd::ctx::prof::stack_usage_here(const ctx &ctx)
|
|||
// ctx_ole.h
|
||||
//
|
||||
|
||||
namespace ircd {
|
||||
namespace ctx {
|
||||
namespace ole {
|
||||
namespace ircd::ctx::ole
|
||||
{
|
||||
using closure = std::function<void () noexcept>;
|
||||
|
||||
using closure = std::function<void () noexcept>;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cond;
|
||||
std::deque<closure> queue;
|
||||
bool interruption;
|
||||
std::thread *thread;
|
||||
|
||||
std::mutex mutex;
|
||||
std::condition_variable cond;
|
||||
std::deque<closure> queue;
|
||||
bool interruption;
|
||||
std::thread *thread;
|
||||
|
||||
closure pop();
|
||||
void worker() noexcept;
|
||||
void push(closure &&);
|
||||
|
||||
} // namespace ole
|
||||
} // namespace ctx
|
||||
} // namespace ircd
|
||||
closure pop();
|
||||
void worker() noexcept;
|
||||
void push(closure &&);
|
||||
}
|
||||
|
||||
ircd::ctx::ole::init::init()
|
||||
{
|
||||
|
|
62
ircd/http.cc
62
ircd/http.cc
|
@ -21,28 +21,34 @@
|
|||
|
||||
#include <ircd/spirit.h>
|
||||
|
||||
namespace ircd {
|
||||
namespace http {
|
||||
namespace ircd::http
|
||||
{
|
||||
namespace spirit = boost::spirit;
|
||||
namespace qi = spirit::qi;
|
||||
namespace ascii = qi::ascii;
|
||||
|
||||
namespace spirit = boost::spirit;
|
||||
namespace qi = spirit::qi;
|
||||
namespace ascii = qi::ascii;
|
||||
using spirit::unused_type;
|
||||
|
||||
using spirit::unused_type;
|
||||
using qi::lit;
|
||||
using qi::string;
|
||||
using qi::char_;
|
||||
using qi::short_;
|
||||
using qi::int_;
|
||||
using qi::long_;
|
||||
using qi::repeat;
|
||||
using qi::omit;
|
||||
using qi::raw;
|
||||
using qi::attr;
|
||||
using qi::eps;
|
||||
|
||||
using qi::lit;
|
||||
using qi::string;
|
||||
using qi::char_;
|
||||
using qi::short_;
|
||||
using qi::int_;
|
||||
using qi::long_;
|
||||
using qi::repeat;
|
||||
using qi::omit;
|
||||
using qi::raw;
|
||||
using qi::attr;
|
||||
using qi::eps;
|
||||
template<class it, class top = unused_type> struct grammar;
|
||||
struct parser extern const parser;
|
||||
|
||||
std::map<code, string_view> reason
|
||||
size_t printed_size(const std::initializer_list<line::header> &headers);
|
||||
size_t print(char *const &buf, const size_t &max, const std::initializer_list<line::header> &headers);
|
||||
}
|
||||
|
||||
std::map<ircd::http::code, ircd::string_view> ircd::http::reason
|
||||
{
|
||||
{ code::CONTINUE, "Continue" },
|
||||
{ code::SWITCHING_PROTOCOLS, "Switching Protocols" },
|
||||
|
@ -82,9 +88,6 @@ std::map<code, string_view> reason
|
|||
{ code::INSUFFICIENT_STORAGE, "Insufficient Storage" },
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace ircd
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
ircd::http::line::request,
|
||||
|
@ -117,12 +120,9 @@ BOOST_FUSION_ADAPT_STRUCT
|
|||
( decltype(ircd::http::query::second), second )
|
||||
)
|
||||
|
||||
namespace ircd {
|
||||
namespace http {
|
||||
|
||||
template<class it,
|
||||
class top = unused_type>
|
||||
struct grammar
|
||||
class top>
|
||||
struct ircd::http::grammar
|
||||
:qi::grammar<it, top>
|
||||
,parse::grammar
|
||||
{
|
||||
|
@ -218,20 +218,14 @@ struct grammar
|
|||
{}
|
||||
};
|
||||
|
||||
struct parser
|
||||
struct ircd::http::parser
|
||||
:grammar<const char *, unused_type>
|
||||
{
|
||||
static size_t content_length(const string_view &val);
|
||||
|
||||
parser(): grammar { grammar::ws, "http.request" } {}
|
||||
}
|
||||
const parser;
|
||||
|
||||
size_t printed_size(const std::initializer_list<line::header> &headers);
|
||||
size_t print(char *const &buf, const size_t &max, const std::initializer_list<line::header> &headers);
|
||||
|
||||
} // namespace http
|
||||
} // namespace ircd
|
||||
const ircd::http::parser;
|
||||
|
||||
size_t
|
||||
ircd::http::print(char *const &buf,
|
||||
|
|
133
ircd/logger.cc
133
ircd/logger.cc
|
@ -34,57 +34,52 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using namespace ircd;
|
||||
|
||||
namespace ircd {
|
||||
namespace log {
|
||||
|
||||
// Option toggles
|
||||
std::array<bool, num_of<facility>()> file_flush;
|
||||
std::array<bool, num_of<facility>()> console_flush;
|
||||
std::array<const char *, num_of<facility>()> console_ansi;
|
||||
|
||||
// Runtime master switches
|
||||
std::array<bool, num_of<facility>()> file_out;
|
||||
std::array<bool, num_of<facility>()> console_out;
|
||||
std::array<bool, num_of<facility>()> console_err;
|
||||
|
||||
// Suppression state (for struct console_quiet)
|
||||
std::array<bool, num_of<facility>()> quieted_out;
|
||||
std::array<bool, num_of<facility>()> quieted_err;
|
||||
|
||||
// Logfile name and device
|
||||
std::array<const char *, num_of<facility>()> fname;
|
||||
std::array<std::ofstream, num_of<facility>()> file;
|
||||
|
||||
/*
|
||||
ConfEntry conf_log_table[] =
|
||||
namespace ircd::log
|
||||
{
|
||||
{ "file_critical", CF_QSTRING, NULL, PATH_MAX, &fname[CRITICAL] },
|
||||
{ "file_error", CF_QSTRING, NULL, PATH_MAX, &fname[ERROR] },
|
||||
{ "file_warning", CF_QSTRING, NULL, PATH_MAX, &fname[WARNING] },
|
||||
{ "file_notice", CF_QSTRING, NULL, PATH_MAX, &fname[NOTICE] },
|
||||
{ "file_info", CF_QSTRING, NULL, PATH_MAX, &fname[INFO] },
|
||||
{ "file_debug", CF_QSTRING, NULL, PATH_MAX, &fname[DEBUG] },
|
||||
};
|
||||
*/
|
||||
// Option toggles
|
||||
std::array<bool, num_of<facility>()> file_flush;
|
||||
std::array<bool, num_of<facility>()> console_flush;
|
||||
std::array<const char *, num_of<facility>()> console_ansi;
|
||||
|
||||
static void open(const facility &fac);
|
||||
static void prefix(const facility &fac, const char *const &date);
|
||||
static void suffix(const facility &fac);
|
||||
// Runtime master switches
|
||||
std::array<bool, num_of<facility>()> file_out;
|
||||
std::array<bool, num_of<facility>()> console_out;
|
||||
std::array<bool, num_of<facility>()> console_err;
|
||||
|
||||
const auto main_thread_id
|
||||
{
|
||||
std::this_thread::get_id()
|
||||
};
|
||||
// Suppression state (for struct console_quiet)
|
||||
std::array<bool, num_of<facility>()> quieted_out;
|
||||
std::array<bool, num_of<facility>()> quieted_err;
|
||||
|
||||
void thread_assertion();
|
||||
// Logfile name and device
|
||||
std::array<const char *, num_of<facility>()> fname;
|
||||
std::array<std::ofstream, num_of<facility>()> file;
|
||||
|
||||
} // namespace log
|
||||
} // namespace ircd
|
||||
/*
|
||||
ConfEntry conf_log_table[] =
|
||||
{
|
||||
{ "file_critical", CF_QSTRING, NULL, PATH_MAX, &fname[CRITICAL] },
|
||||
{ "file_error", CF_QSTRING, NULL, PATH_MAX, &fname[ERROR] },
|
||||
{ "file_warning", CF_QSTRING, NULL, PATH_MAX, &fname[WARNING] },
|
||||
{ "file_notice", CF_QSTRING, NULL, PATH_MAX, &fname[NOTICE] },
|
||||
{ "file_info", CF_QSTRING, NULL, PATH_MAX, &fname[INFO] },
|
||||
{ "file_debug", CF_QSTRING, NULL, PATH_MAX, &fname[DEBUG] },
|
||||
};
|
||||
*/
|
||||
|
||||
static void open(const facility &fac);
|
||||
static void prefix(const facility &fac, const char *const &date);
|
||||
static void suffix(const facility &fac);
|
||||
|
||||
const auto main_thread_id
|
||||
{
|
||||
std::this_thread::get_id()
|
||||
};
|
||||
|
||||
void thread_assertion();
|
||||
}
|
||||
|
||||
void
|
||||
log::init()
|
||||
ircd::log::init()
|
||||
{
|
||||
//TODO: XXX: config + cmd control + other fancy stuff
|
||||
|
||||
|
@ -127,13 +122,13 @@ log::init()
|
|||
}
|
||||
|
||||
void
|
||||
log::fini()
|
||||
ircd::log::fini()
|
||||
{
|
||||
//remove_top_conf("log");
|
||||
}
|
||||
|
||||
void
|
||||
log::open()
|
||||
ircd::log::open()
|
||||
{
|
||||
for_each<facility>([](const facility &fac)
|
||||
{
|
||||
|
@ -153,7 +148,7 @@ log::open()
|
|||
}
|
||||
|
||||
void
|
||||
log::close()
|
||||
ircd::log::close()
|
||||
{
|
||||
for_each<facility>([](const facility &fac)
|
||||
{
|
||||
|
@ -163,7 +158,7 @@ log::close()
|
|||
}
|
||||
|
||||
void
|
||||
log::flush()
|
||||
ircd::log::flush()
|
||||
{
|
||||
for_each<facility>([](const facility &fac)
|
||||
{
|
||||
|
@ -172,7 +167,7 @@ log::flush()
|
|||
}
|
||||
|
||||
void
|
||||
log::open(const facility &fac)
|
||||
ircd::log::open(const facility &fac)
|
||||
try
|
||||
{
|
||||
const auto &mode(std::ios::app);
|
||||
|
@ -189,7 +184,7 @@ catch(const std::exception &e)
|
|||
throw;
|
||||
}
|
||||
|
||||
log::console_quiet::console_quiet(const bool &showmsg)
|
||||
ircd::log::console_quiet::console_quiet(const bool &showmsg)
|
||||
{
|
||||
if(showmsg)
|
||||
notice("Log messages are now quieted at the console");
|
||||
|
@ -200,25 +195,25 @@ log::console_quiet::console_quiet(const bool &showmsg)
|
|||
std::fill(begin(console_err), end(console_err), false);
|
||||
}
|
||||
|
||||
log::console_quiet::~console_quiet()
|
||||
ircd::log::console_quiet::~console_quiet()
|
||||
{
|
||||
std::copy(begin(quieted_out), end(quieted_out), begin(console_out));
|
||||
std::copy(begin(quieted_err), end(quieted_err), begin(console_err));
|
||||
}
|
||||
|
||||
log::log::log(const std::string &name)
|
||||
ircd::log::log::log(const std::string &name)
|
||||
:name{name}
|
||||
{
|
||||
}
|
||||
|
||||
log::log::log(const std::string &name,
|
||||
ircd::log::log::log(const std::string &name,
|
||||
const char &snote)
|
||||
:log{name}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
log::mark(const char *const &msg)
|
||||
ircd::log::mark(const char *const &msg)
|
||||
{
|
||||
for_each<facility>([&msg]
|
||||
(const auto &fac)
|
||||
|
@ -228,8 +223,8 @@ log::mark(const char *const &msg)
|
|||
}
|
||||
|
||||
void
|
||||
log::mark(const facility &fac,
|
||||
const char *const &msg)
|
||||
ircd::log::mark(const facility &fac,
|
||||
const char *const &msg)
|
||||
{
|
||||
slog(fac, [&msg]
|
||||
(std::ostream &s)
|
||||
|
@ -241,9 +236,9 @@ log::mark(const facility &fac,
|
|||
}
|
||||
|
||||
void
|
||||
log::vlog(const facility &fac,
|
||||
const char *const &fmt,
|
||||
const va_rtti &ap)
|
||||
ircd::log::vlog(const facility &fac,
|
||||
const char *const &fmt,
|
||||
const va_rtti &ap)
|
||||
{
|
||||
char buf[1024];
|
||||
fmt::vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
|
@ -256,10 +251,10 @@ log::vlog(const facility &fac,
|
|||
}
|
||||
|
||||
void
|
||||
log::vlog(const facility &fac,
|
||||
const std::string &name,
|
||||
const char *const &fmt,
|
||||
const va_rtti &ap)
|
||||
ircd::log::vlog(const facility &fac,
|
||||
const std::string &name,
|
||||
const char *const &fmt,
|
||||
const va_rtti &ap)
|
||||
{
|
||||
char buf[1024];
|
||||
fmt::vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
|
@ -271,8 +266,8 @@ log::vlog(const facility &fac,
|
|||
}
|
||||
|
||||
void
|
||||
log::slog(const facility &fac,
|
||||
const std::function<void (std::ostream &)> &closure)
|
||||
ircd::log::slog(const facility &fac,
|
||||
const std::function<void (std::ostream &)> &closure)
|
||||
{
|
||||
void thread_assertion();
|
||||
|
||||
|
@ -300,8 +295,8 @@ log::slog(const facility &fac,
|
|||
}
|
||||
|
||||
void
|
||||
log::prefix(const facility &fac,
|
||||
const char *const &date)
|
||||
ircd::log::prefix(const facility &fac,
|
||||
const char *const &date)
|
||||
{
|
||||
const auto console_prefix([&fac, &date]
|
||||
(auto &stream)
|
||||
|
@ -329,7 +324,7 @@ log::prefix(const facility &fac,
|
|||
}
|
||||
|
||||
void
|
||||
log::suffix(const facility &fac)
|
||||
ircd::log::suffix(const facility &fac)
|
||||
{
|
||||
const auto console_newline([&fac]
|
||||
(auto &stream)
|
||||
|
@ -362,7 +357,7 @@ log::suffix(const facility &fac)
|
|||
}
|
||||
|
||||
const char *
|
||||
log::reflect(const facility &f)
|
||||
ircd::log::reflect(const facility &f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue