0
0
Fork 0
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:
Jason Volk 2017-08-28 14:51:22 -07:00
parent 28cf226c3a
commit d9a4f06bf6
54 changed files with 1427 additions and 1457 deletions

View file

@ -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()()

View file

@ -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)

View file

@ -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)
{

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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 &notes(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 &notes(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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)
};

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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 &()
{

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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")
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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 &section);
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 &section);
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)

View file

@ -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,

View file

@ -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)

View file

@ -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

View file

@ -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}
{
}

View file

@ -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)
{

View file

@ -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"

View file

@ -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

View file

@ -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()
{

View file

@ -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,

View file

@ -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)
{