Add string comparison functions to basic_sstring that are required for
C++ containers such as std::map and std::multimap.
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
The way periodic timers are rearmed during timer completion causes
timer_settime() to be called twice for each periodic timer completion:
once during rearm and second time by enable_fn(). Fix it by providing
another function that only re-adds timer into timers container, but do
not call timer_settime().
So that the callback which is set on it and which is allocated on CPU
0 is destroyed on CPU 0 when the clock dies. Otherwise we can attempt
to delete it after the CPU thread is gone if CPU 0 != main thread.
When smp::configure() is called from non-main thread, then the global
state which it allocates will be destroyed after reactor is destroyed,
because it will be destroyed from the main thread and the reactor will
be destroyed together with the thread which called
smp::configure(). This will result in SIGSEGV when allocator tries to
free _threads vector across CPU threads because the target CPU was
alrady freed. See issue #10.
To fix this, I introduced smp::cleanup() method which should cleanup
all global state and should be called in the same thread in which
smp::configure() was called.
I need to call smp::configure() from non-main thread for integration
with boost unit testing framework.
Instead of scheduling timer processing to happen in the future,
process timers in the context of the poller (signal poller for high
resolution timer, lowres time poller for low resolution timers).
This both reduces timer latency (not very important) but removes a
use of promise/future in a repetitive task, which is error prone.
Incoming item processing usually takes more work then completion
item processing. Prefetch more completion items to make sure they are
ready before access.
Turn a condition into an assert() since if a mapping is invalid this may
only mean that we have a bug.
Signed-off-by: Vlad Zolotarov <vladz@cloudius-systems.com>
receive_signal() uses the unordered map _signal_handlers (signo mapped to
signal_handler) to either register a signal or find an existing one, and
from there get a future from the promise associated with that signal.
The problem is _signal_handlers.emplace() being called unconditionally,
resulting in the constructor from signal_handler always being called to
needlessly re-register the same handler, even when the signo is already
inserted in the map.
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
Tell all waiters that something bad happened and they should all go away.
Can be used only once; waiters should clean up and there must not be any
new waiters.
When size > align, we simply call the small allocator with the provided size,
but that does not guarantee any alignment above the default.
Round the allocation size to the nearest power of two in that case, to
guarantee alignment.
Calling state.get() will throw the exception instead of calling the function,
thus denying the called function the chance to deal with the exception.
Fix by constructing the future directly from state.
Currently we require that memory be freed on the same cpu it was allocated.
This does not impose difficulties on the user code, since our code is already
smp-unsafe, and so must use message-passing to run the destructor on the
origin cpu, so memory is naturally freed there as well.
However, library code does not run under our assumptions, specifically
std::exception_ptr, which we do transport across cores.
To support this use case, add low-performance support for cross-cpu frees,
using an atomic singly linked list per core.
It only supports -help at the moment. It is quite annoying to see:
$ ./httpd -h
terminate called after throwing an instance of
'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::program_options::unknown_option> >'
what(): unrecognised option '-h'
Aborted
Support both -h and --help.