[
  {
    "path": ".gitignore",
    "content": ".vscode\n.clangd\nbuild\ncompile_commands.json"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.2)\nproject(rocket CXX)\n\noption(BUILD_EXAMPLES \"Build examples\" ON)\n\n# C++ standard\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n# generate compile_commands.json if possible\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\n# include dir of rocket.hpp\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\n\nif(BUILD_EXAMPLES)\n    message(STATUS \"build examples\")\n    add_executable(example example.cpp)    \nendif()\n"
  },
  {
    "path": "README.md",
    "content": "# rocket - Fast C++ Observer Pattern\n\nRocket is a public-domain, single-header implementation of a signal/slots library for C++.\n\nThe library was developed because existing solutions were too inflexible, too slow, or came as a part of a larger dependency (for example boost::signals and boost::signals2).\n\n## Design goals\n\n1. Efficiency. The library takes special care to not use cache unfriendly code (such as calling virtual methods) unless absolutely necessary.\n2. Low memory footprint (does not allocate during signal emission).\n3. Modern C++. No bloat from overloading 50 template specializations for each function.\n4. Single header file implementation.\n5. No dependencies.\n\nThe API was heavily inspired by boost::signals2. If you are already familiar with boost::signals2, switching to rocket will be a no brainer.\n\n## What makes rocket unique?\n\n1. The library provides both a thread-safe and a thread-unsafe implementation. No efficiency loss due to locks or atomics in the thread-unsafe implementation.\n2. Policy based design. Specify at declaration time and invocation time of the signal how _you_ want the call results to be returned.\n3. The signals are reentrant. This property is a must have for any event processing library because it must be possible to recursively emit signals, or disconnect slots from within a signal handler.\n4. Support for smart `scoped_connection`'s and `scoped_connection_container`'s.\n5. Support for automatic lifetime tracking of observers via `rocket::trackable`.\n6. Allows slots to get an instance to the `current_connection` object (see example 5).\n7. Allows slots to preemtively abort the emission of the signal (see example 6).\n8. Support for Qt-style `queued_connection`'s. If a slot is connected to a signal with this flag, the slots execution will be scheduled on the same thread that connected the slot to the signal (see example 7).\n9. Supports `set_interval` and `set_timeout` functions to connect periodic events to the current threads dispatch queue (you can opt-out of this feature by defining `ROCKET_NO_TIMERS`).\n\n\n## Performance\n\nBecause the main focus of this library was to provide an efficient single threaded implementation, `rocket::signal` has about the same overhead as an iteration through an `std::list<std::function<T>>`.\n\nHere are some performance benchmarks between boost::signals2 and rocket for registering 10 slots to each signal type and emitting each one 1000 times.\n\n| Library         | Avg. execution time |\n| --------------  | -------------------:|\n| boost::signals2 |          810.389 µs |\n| rocket::signal  |           98.155 µs |\n\n## 1. Creating your first signal\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    rocket::signal<void()> thread_unsafe_signal;\n    rocket::thread_safe_signal<void()> thread_safe_signal;\n\n    // Connecting the first handler to our signal\n    thread_unsafe_signal.connect([]() {\n        std::cout << \"First handler called!\" << std::endl;\n    });\n    \n    // Connecting a second handler to our signal using alternative syntax\n    thread_unsafe_signal += []() {\n        std::cout << \"Second handler called!\" << std::endl;\n    };\n    \n    // Invoking the signal\n    thread_unsafe_signal();\n}\n\n// Output:\n//     First handler called!\n//     Second handler called!\n```\n\n## 2. Connecting class methods to the signal\n\n```cpp\n#include <string>\n#include <iostream>\n\nclass Subject {\npublic:\n    void setName(const std::string& newName)\n    {\n        if (name != newName) {\n            name = newName;\n            nameChanged(newName);\n        }\n    }\n\npublic:\n    rocket::signal<void(std::string)> nameChanged;\n\nprivate:\n    std::string name;\n};\n\nclass Observer {\npublic:\n    Observer(Subject& subject)\n    {\n        // Register the `onNameChanged`-function of this object as a listener and\n        // store the resultant connection object in the listener's connection set.\n\n        // This is all your need to do for the most common case, if you want the\n        // connection to be broken when the observer is destroyed.\n        connections += {\n            subject.nameChanged.connect<&Observer::onNameChanged>(this)\n        };\n    }\n\n    void onNameChanged(const std::string& name)\n    {\n        std::cout << \"Subject received new name: \" << name << std::endl;\n    }\n\nprivate:\n    rocket::scoped_connection_container connections;\n};\n\nint main()\n{\n    Subject s;\n    Observer o{ s };\n    s.setName(\"Peter\");\n}\n\n// Output:\n//     Subject received new name: Peter\n```\n\n### Another example: Binding pure virtual interface methods\n\n```cpp\n#include <string>\n#include <iostream>\n#include <memory>\n\nclass ILogger {\npublic:\n    virtual void logMessage(const std::string& message) = 0;\n};\n\nclass ConsoleLogger : public ILogger {\npublic:\n    void logMessage(const std::string& message) override {\n        std::cout << \"New log message: \" << message << std::endl;\n    }\n};\n\nclass App {\npublic:\n    void run()\n    {\n        if (work()) {\n            onSuccess(\"I finished my work!\");\n        }\n    }\n    \n    bool work()\n    {\n        return true;\n    }\n    \npublic:\n    rocket::signal<void(std::string)> onSuccess;\n};\n\nint main()\n{\n    std::unique_ptr<App> app = std::make_unique<App>();\n\n    std::unique_ptr<ILogger> logger = std::make_unique<ConsoleLogger>();\n    app->onSuccess.connect<&ILogger::logMessage>(logger.get());\n\n    app->run();\n}\n\n// Output:\n//     New log message: I finished my work!\n```\n\n## 3.a Handling lifetime and scope of connection objects\n\nWhat if we want to destroy our logger instance from example 2 but continue to use the app instance?\n\n**Solution:** We use `scoped_connection`-objects to track our connected slots!\n\n```cpp\n// [...] (See example 2)\n\nint main()\n{\n    std::unique_ptr<App> app = std::make_unique<App>();\n    {\n        std::unique_ptr<ILogger> logger = std::make_unique<ConsoleLogger>();\n        \n        rocket::scoped_connection connection = app->onSuccess\n            .connect(logger.get(), &ILogger::logMessage);\n            \n        app->run();\n    } //<-- `logger`-instance is destroyed at the end of this block\n      //<-- The `connection`-object is also destroyed here\n      //        and therefore removed from App::onSuccess.\n     \n    // Run the app a second time\n    //\n    // This would normally cause a crash / undefined behavior because the logger\n    // instance is destroyed at this point, but App::onSuccess still referenced it\n    // in example 2.\n   \n    app->run();\n}\n\n// Output:\n//     New log message: I finished my work!\n```\n\n## 3.b Advanced lifetime tracking\n\nThe library can also track the lifetime of your class objects for you, if the connected slot instances inherit from the `rocket::trackable` base class.\n\n```cpp\n// [...] (See example 2)\n\nstruct ILogger : rocket::trackable\n{\n    virtual void logMessage(const std::string& message) = 0;\n};\n\n// [...] (See example 2)\n\nint main()\n{\n    std::unique_ptr<App> app = std::make_unique<App>();\n    {\n        std::unique_ptr<ILogger> logger = std::make_unique<ConsoleLogger>();\n        app->onSuccess.connect(logger.get(), &ILogger::logMessage);\n        \n        app->run();\n    } //<-- `logger`-instance is destroyed at the end of this block\n    \n      //<-- Because `ILogger` inherits from `rocket::trackable`, the signal knows\n      //        about its destruction and will automatically disconnect the slot!\n      \n    // Run the app a second time\n    //\n    // This would normally cause a crash / undefined behavior because the logger\n    // instance is destroyed at this point, but App::onSuccess still referenced it\n    // in example 2.\n    \n    app->run();\n}\n```\n\n## 4. Getting return values from a call to a signal\n\nSlots can also return values to the emitting signal.\nBecause a signal can have several slots attached to it, the return values are collected by using the so called `value collectors`.\n\nThe default value collector returns an `optional<T>` from a call to a `signal<T(...)>::operator()`\n\nHowever, this behaviour can be overriden at declaration time of the signal as well as during signal invocation.\n\n```cpp\n#include <cmath>\n#include <iostream>\n\nint main()\n{\n    rocket::signal<int(int)> signal;\n    \n    // The library supports argument and return type transformation between the\n    // signal and the slots. We show this by connecting the `float sqrtf(float)`\n    // function to a signal with an `int` argument and `int` return value.\n    \n    signal.connect(std::sqrtf);\n    \n    std::cout << \"Computed value: \" << *signal(16);\n}\n\n// Output:\n//     Computed value: 4\n```\n\n```cpp\n#include <cmath>\n#include <iostream>\n#include <iomanip>\n\nint main()\n{\n    // Because we set `rocket::range` as the value collector for this signal\n    // calling operator() now returns the return values of all connected slots.\n    \n    rocket::signal<float(float), rocket::range<float>> signal;\n    \n    // Lets connect a couple more functions to our signal and print all the\n    // return values.\n    \n    signal.connect(std::sinf);\n    signal.connect(std::cosf);\n    \n    std::cout << std::fixed << std::setprecision(2);\n    \n    for (auto result : signal(3.14159)) {\n        std::cout << result << std::endl;\n    }\n    \n    // We can also override the return value collector at invocation time\n    std::cout << \"First return value: \" << signal.invoke<rocket::first<float>>(3.14159);\n    std::cout << std::endl;\n    std::cout << \"Last return value: \" << signal.invoke<rocket::last<float>>(3.14159);\n}\n\n// Output:\n//     0.00\n//     -1.00\n//     First return value: 0.00\n//     Last return value: -1.00\n```\n\n## 5. Accessing the current connection object inside a slot\n\nSometimes it is desirable to get an instance to the current connection object inside of a slot function. An example would be if you want to make a callback that only fires once and then disconnects itself from the signal that called it.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    rocket::signal<void()> signal;\n\n    signal.connect([] {\n        std::cout << \"Slot called. Now disconnecting...\" << std::endl;\n        \n        // `current_connection` is stored in thread-local-storage.\n        rocket::current_connection().disconnect();\n    });\n    \n    signal();\n    signal();\n    signal();\n}\n\n// Output:\n//     Slot called. Now disconnecting...\n```\n\n## 6. Preemtively aborting the emission of a signal\n\nA slot can preemtively abort the emission of a signal if it needs to. This is useful in scenarios where your slot functions try to find some value and you just want the result of the first slot that found one and stop other slots from running.\n\n```cpp\n#include <iostream>\n\nint main()\n{\n    rocket::signal<void()> signal;\n    \n    signal.connect([] {\n        std::cout << \"First slot called. Aborting emission of other slots.\" << std::endl;\n        \n        rocket::abort_emission();\n        // Notice that this doesn't disconnect the other slots. It just breaks out of the\n        // signal emitting loop.\n    });\n \n    signal.connect([] {\n        std::cout << \"Second slot called. Should never happen.\" << std::endl;\n    });\n    \n    signal();\n}\n\n// Output:\n//     First slot called. Aborting emission of other slots.\n```\n\n## 7. Using `queued_connection` to build a message queue between threads\n\nAn observer can connect slots to a subject with the `queued_connection`-flag. Instead of calling the slot directly when the signal is invoked, rocket will schedule the execution in the same thread from where the observer called the `connect`-function. With this system it is extremely easy to build a message queue between different threads.\n\nLets say we have a subject called `ModelFileLoaderThread`. It loads files from disc and does some expensive preprocessing.\nWe also have an observer. The `RenderThread`. The `RenderThread` now wants to know whenever a new file is fully loaded, so it can display it in the scene.\n\n```cpp\nclass ModelFileLoaderThread {\npublic:\n    void start() {\n        shouldRun = true;\n        thread = std::thread(&ModelFileLoaderThread::run, this);\n    }\n\n    void shutdown() {\n        shouldRun = false;\n        thread.join();\n    }\n\n    void pushLoadRequest(const std::string& fileName) {\n        std::scoped_lock<std::mutex> guard{ mutex };\n        loadRequests.push_front(fileName);\n    }\n\nprivate:\n    void run() {\n        while (shouldRun) {\n            std::forward_list<std::string> requests;\n            {\n                std::scoped_lock<std::mutex> guard{ mutex };\n                loadRequests.swap(requests);\n            }\n            for (auto& fileName : requests) {\n                ModelFilePtr modelFile = new ModelFile(fileName);\n\n                if (modelFile->loadModel()) {\n                    modelLoaded(modelFile);\n                } else {\n                    modelLoadFailed(fileName);\n                }\n            }\n            std::this_thread::sleep_for(std::chrono::milliseconds(50));\n        }\n    }\n    \npublic:\n    rocket::thread_safe_signal<void(ModelFilePtr)> modelLoaded;\n    rocket::thread_safe_signal<void(std::string)> modelLoadFailed;\n\nprivate:\n    std::thread thread;\n    volatile bool shouldRun = false;\n    \n    std::mutex mutex;\n    std::forward_list<std::string> loadRequests;\n};\n```\n\n```cpp\nclass RenderThread {\npublic:\n    void initialize() {\n        modelLoaderThread.start();\n\n        // Connect to the thread using queued_connection flag\n        modelLoaderThread.modelLoaded.connect<&RenderThread::onModelLoaded>(this, rocket::queued_connection);\n        modelLoaderThread.modelLoadFailed.connect<&RenderThread::onModelLoadFailed>(this, rocket::queued_connection);\n    }\n    \n    void shutdown() {\n        modelLoaderThread.shutdown();\n    }\n    \n    void render() {\n        rocket::dispatch_queued_calls();    //<-- This call is required so rocket can call the queued slots from this thread\n  \n        for (IRenderablePtr& renderable : renderables) {\n            renderable->render();\n        }\n    }\n    \nprivate:\n    // These slots are actually executed from inside the `rocket::dispatch_queued_calls` method\n\n    void onModelLoaded(ModelFilePtr const& modelFile) {\n        // No lock needed, because onModelLoaded is called on render thread!\n        renderables.push_back(new ModelRenderer(modelFile));\n    }\n\n    void onModelLoadFailed(std::string const& fileName) {\n        // Show log message\n    }\n    \nprivate:\n    std::list<IRenderablePtr> renderables;\n    ModelFileLoaderThread modelLoaderThread;\n};\n```\n\n## 8. Using `set_interval` and `set_timeout`\n\nOther than signals and slots, rocket can also schedule timers for you! They work similar to the `queued_connections` shown in example 7.\n\n```cpp\n// [...] (See example 7)\n\nclass RenderThread {\npublic:\n    void initialize() {\n        modelLoaderThread.start();\n\n        connections += {\n            // Register a timer that gets called every 5000 ms\n            rocket::set_interval<&RenderThread::onClearRenderablesTimerExpired>(this, 5000),\n            \n            // Connect to the thread using queued_connection flag\n            modelLoaderThread.modelLoaded.connect<&RenderThread::onModelLoaded>(this, rocket::queued_connection),\n            modelLoaderThread.modelLoadFailed.connect<&RenderThread::onModelLoadFailed>(this, rocket::queued_connection)\n        };\n    }\n\n    void shutdown() {\n        modelLoaderThread.shutdown();\n    }\n    \n    void render() {\n        rocket::dispatch_queued_calls();    //<-- This call is required so rocket can call the queued slots from this thread\n  \n        for (IRenderablePtr& renderable : renderables) {\n            // Will be rendered for at most 5 seconds because `onClearRenderablesTimerExpired` periodically clears the renderables\n            renderable->render();\n        }\n    }\n    \nprivate:\n    // These slots are actually executed from inside the `rocket::dispatch_queued_calls` method\n\n    void onModelLoaded(ModelFilePtr const& modelFile) {\n        // No lock needed, because onModelLoaded is called on render thread!\n        renderables.push_back(new ModelRenderer(modelFile));\n    }\n\n    void onModelLoadFailed(std::string const& fileName) {\n        // Show log message\n    }\n\n    void onClearRenderablesTimerExpired() {\n        // Called every 5000 ms from inside the `rocket::dispatch_queud_calls` method\n        renderables.clear();\n    }\n\nprivate:\n    rocket::scoped_connection_container connections;\n\n    std::list<IRenderablePtr> renderables;\n    ModelFileLoaderThread modelLoaderThread;\n};\n```\n"
  },
  {
    "path": "example.cpp",
    "content": "\n#include \"rocket.hpp\"\n#include <iostream>\n\nstruct Testing : rocket::trackable\n{\n    int hello(float a)\n    {\n        std::cout << \"Testing: \" << a << std::endl;\n        return 0;\n    }\n};\n\nstruct NonDefaultConstructible\n{\n    explicit NonDefaultConstructible(int x)\n        : value{ x }\n    {\n    }\n\n    ~NonDefaultConstructible()\n    {\n        std::cout << \"Destructor called for value: \" << value << std::endl;\n    }\n\n    NonDefaultConstructible(NonDefaultConstructible&& n)\n        : value{ n.value }\n    {\n        n.value = 0;\n    }\n\n    NonDefaultConstructible& operator = (NonDefaultConstructible&& n)\n    {\n        value = n.value;\n        n.value = 0;\n        return *this;\n    }\n\nprivate:\n    int value;\n\n    NonDefaultConstructible() = delete;\n\n    NonDefaultConstructible(NonDefaultConstructible const&) = delete;\n    NonDefaultConstructible& operator = (NonDefaultConstructible const&) = delete;\n};\n\nstruct TestShared : std::enable_shared_from_this<TestShared>\n{\n    int hello(int a)\n    {\n        return 321;\n    }\n};\n\nint main()\n{\n    NonDefaultConstructible n{ 1337 };\n    {\n        rocket::stable_list<NonDefaultConstructible> list;\n        list.push_back(std::move(n));\n    }\n    {\n        rocket::stable_list<int> list1{ 1, 2, 3, 4, 5 };\n        rocket::stable_list<int> list2{ list1.crbegin(), list1.crend() };\n\n        list2.resize(3);\n        std::cout << \"List size: \" << list2.size() << std::endl;\n\n        for (auto elem : list2)\n            std::cout << elem << ' ';\n\n        std::cout << std::endl;\n    }\n\n    rocket::signal<int(int)> test;\n\n    test.connect([](int x) {\n        return x * 3;\n    });\n    test.connect([](int x) {\n        return x * 1;\n    });\n    test.connect([](int x) {\n        return x * 2;\n    });\n\n    {\n        // Give me the minimal value of all slots\n        typedef rocket::minimum<int> selector;\n\n        std::cout << \"Minimum: \" << test.invoke<selector>(5) << std::endl;\n    }\n\n    {\n        // Give me the last result in an optional (default behaviour)\n        rocket::optional<int> r{ test(5) };\n        std::cout << \"Optional: \" << *r << std::endl;\n    }\n\n    // Connect a new slot via scoped connections\n    {\n        rocket::scoped_connection scoped{\n            test.connect([](int x) {\n                return x * 4;\n            })\n        };\n\n        // Give me all results in a list\n        typedef rocket::range<int> selector;\n\n        std::cout << \"Range: \";\n\n        for (int x : test.invoke<selector>(5)) {\n            std::cout << x << \" \";\n        }\n        std::cout << std::endl;\n    }\n\n    {\n        // The connections are only connected as long as the testing-object is alive\n        Testing testing;\n\n        test.connect(testing, &Testing::hello);\n        test.connect(testing, &Testing::hello);\n\n        test(1337);\n    }\n\n    {\n        auto classPtr = std::make_shared<TestShared>();\n        auto f = rocket::bind_weak_ptr(classPtr, &TestShared::hello);\n        f(2);\n    }\n\n    {\n        // A slot that kills itself after the first call\n        test.connect([](int) {\n            // Get the connection object associated with this slot and kill it\n            rocket::current_connection().disconnect();\n\n            std::cout << \"called slot disconnect!\" << std::endl;\n            return 0;\n        });\n\n        test(1337);\n        test(1337);\n    }\n\n    {\n        // A slot that aborts emission after the first call\n        test.connect([](int) {\n            rocket::abort_emission();\n\n            std::cout << \"called abort!\" << std::endl;\n            return 0;\n        });\n\n        test.connect([](int) {\n            std::cout << \"This should never show up, as the previous slot aborts the emission!\" << std::endl;\n            return 0;\n        });\n\n        test(1337);\n    }\n\n    std::cin.get();\n    return 0;\n}\n\n"
  },
  {
    "path": "rocket.hpp",
    "content": "/***********************************************************************************\n * rocket - lightweight & fast signal/slots & utility library                      *\n *                                                                                 *\n *   v2.1 - public domain                                                          *\n *   no warranty is offered or implied; use this code at your own risk             *\n *                                                                                 *\n * AUTHORS                                                                         *\n *                                                                                 *\n *   Written by Michael Bleis                                                      *\n *                                                                                 *\n *                                                                                 *\n * LICENSE                                                                         *\n *                                                                                 *\n *   This software is dual-licensed to the public domain and under the following   *\n *   license: you are granted a perpetual, irrevocable license to copy, modify,    *\n *   publish, and distribute this file as you see fit.                             *\n ***********************************************************************************/\n\n#ifndef ROCKET_HPP_INCLUDED\n#define ROCKET_HPP_INCLUDED\n\n/***********************************************************************************\n * CONFIGURATION                                                                   *\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable exceptions.                                  *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_EXCEPTIONS\n#    define ROCKET_NO_EXCEPTIONS\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable the `stable_list` collection in rocket.      *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_STABLE_LIST\n#    define ROCKET_NO_STABLE_LIST\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable `set_timeout` and `set_interval` features.   *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_TIMERS\n#    define ROCKET_NO_TIMERS\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable the connection blocking feature.             *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n#    define ROCKET_NO_BLOCKING_CONNECTIONS\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable the queued connection feature.               *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n#    define ROCKET_NO_QUEUED_CONNECTIONS\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Define this if you want to disable the smart pointer extensions feature.        *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_NO_SMARTPOINTER_EXTENSIONS\n#    define ROCKET_NO_SMARTPOINTER_EXTENSIONS\n#endif\n\n/***********************************************************************************\n * ------------------------------------------------------------------------------- *\n * Redefine this if your compiler doesn't support the `thread_local`-keyword.      *\n * For Visual Studio < 2015 you can define it to `__declspec(thread)` for example. *\n * ------------------------------------------------------------------------------- */\n\n#ifndef ROCKET_THREAD_LOCAL\n#    define ROCKET_THREAD_LOCAL thread_local\n#endif\n\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <forward_list>\n#include <functional>\n#include <initializer_list>\n#include <limits>\n#include <list>\n#include <mutex>\n#include <optional>\n#include <type_traits>\n#include <utility>\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n#    include <deque>\n#    include <future>\n#    include <thread>\n#    include <tuple>\n#    include <unordered_map>\n#endif\n\n#ifndef ROCKET_NO_EXCEPTIONS\n#    include <exception>\n#endif\n\n#ifndef ROCKET_NO_SMARTPOINTER_EXTENSIONS\n#    include <memory>\n#endif\n\n#if !defined(ROCKET_NO_STABLE_LIST) || !defined(ROCKET_NO_QUEUED_CONNECTIONS)\n#    include <iterator>\n#endif\n\n#if !defined(ROCKET_NO_TIMERS) || !defined(ROCKET_NO_QUEUED_CONNECTIONS)\n#    include <chrono>\n#endif\n\n#if __has_cpp_attribute(likely)\n#    define ROCKET_LIKELY [[likely]]\n#else\n#    define ROCKET_LIKELY\n#endif\n\n#if __has_cpp_attribute(unlikely)\n#    define ROCKET_UNLIKELY [[unlikely]]\n#else\n#    define ROCKET_UNLIKELY\n#endif\n\n#if __has_cpp_attribute(maybe_unused)\n#    define ROCKET_MAYBE_UNUSED [[maybe_unused]]\n#else\n#    define ROCKET_MAYBE_UNUSED\n#endif\n\n#if __has_cpp_attribute(nodiscard)\n#    define ROCKET_NODISCARD [[nodiscard]]\n#else\n#    define ROCKET_NODISCARD\n#endif\n\n#if __has_cpp_attribute(no_unique_address)\n#    define ROCKET_NO_UNIQUE_ADDRESS [[no_unique_address]]\n#else\n#    if defined(_MSC_VER) && __cplusplus >= 202002L\n#        define ROCKET_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]\n#    else\n#        define ROCKET_NO_UNIQUE_ADDRESS\n#    endif\n#endif\n\nnamespace rocket\n{\n    template <class T>\n    struct minimum\n    {\n        using value_type = T;\n        using result_type = T;\n\n        template <class U>\n        void operator()(U&& value)\n        {\n            if (!has_value || value < current)\n            {\n                current = std::forward<U>(value);\n                has_value = true;\n            }\n        }\n\n        ROCKET_NODISCARD result_type result()\n        {\n            return std::move(current);\n        }\n\n    private:\n        value_type current{};\n        bool has_value{ false };\n    };\n\n    template <class T>\n    struct maximum\n    {\n        using value_type = T;\n        using result_type = T;\n\n        template <class U>\n        void operator()(U&& value)\n        {\n            if (!has_value || value > current)\n            {\n                current = std::forward<U>(value);\n                has_value = true;\n            }\n        }\n\n        ROCKET_NODISCARD result_type result()\n        {\n            return std::move(current);\n        }\n\n    private:\n        value_type current{};\n        bool has_value{ false };\n    };\n\n    template <class T>\n    struct first\n    {\n        using value_type = T;\n        using result_type = T;\n\n        template <class U>\n        void operator()(U&& value)\n        {\n            if (!has_value)\n            {\n                current = std::forward<U>(value);\n                has_value = true;\n            }\n        }\n\n        ROCKET_NODISCARD result_type result()\n        {\n            return std::move(current);\n        }\n\n    private:\n        value_type current{};\n        bool has_value{ false };\n    };\n\n    template <class T>\n    struct last\n    {\n        using value_type = T;\n        using result_type = T;\n\n        template <class U>\n        void operator()(U&& value)\n        {\n            current = std::forward<U>(value);\n        }\n\n        ROCKET_NODISCARD result_type result()\n        {\n            return std::move(current);\n        }\n\n    private:\n        value_type current{};\n    };\n\n    template <class T>\n    struct range\n    {\n        using value_type = T;\n        using result_type = std::list<T>;\n\n        template <class U>\n        void operator()(U&& value)\n        {\n            values.emplace_back(std::forward<U>(value));\n        }\n\n        ROCKET_NODISCARD result_type result()\n        {\n            return std::move(values);\n        }\n\n    private:\n        std::list<value_type> values;\n    };\n\n#ifndef ROCKET_NO_EXCEPTIONS\n    struct error : std::exception\n    {\n    };\n\n    struct bad_optional_access final : error\n    {\n        const char* what() const noexcept override\n        {\n            return \"rocket: Bad optional access.\";\n        }\n    };\n\n    struct invocation_slot_error final : error\n    {\n        const char* what() const noexcept override\n        {\n            return \"rocket: One of the slots has raised an exception during the signal invocation.\";\n        }\n    };\n#endif\n\n    template <class T>\n    using optional = std::optional<T>;\n\n    template <class T>\n    struct intrusive_ptr final\n    {\n        using value_type = T;\n        using element_type = T;\n        using pointer = T*;\n        using reference = T&;\n\n        template <class U>\n        friend struct intrusive_ptr;\n\n        constexpr intrusive_ptr() noexcept\n            : ptr{ nullptr }\n        {\n        }\n\n        constexpr intrusive_ptr(std::nullptr_t) noexcept\n            : ptr{ nullptr }\n        {\n        }\n\n        explicit intrusive_ptr(pointer p) noexcept\n            : ptr{ p }\n        {\n            if (ptr)\n            {\n                ptr->addref();\n            }\n        }\n\n        intrusive_ptr(intrusive_ptr const& p) noexcept\n            : ptr{ p.ptr }\n        {\n            if (ptr)\n            {\n                ptr->addref();\n            }\n        }\n\n        intrusive_ptr(intrusive_ptr&& p) noexcept\n            : ptr{ p.ptr }\n        {\n            p.ptr = nullptr;\n        }\n\n        template <class U>\n        explicit intrusive_ptr(intrusive_ptr<U> const& p) noexcept\n            : ptr{ p.ptr }\n        {\n            if (ptr)\n            {\n                ptr->addref();\n            }\n        }\n\n        template <class U>\n        explicit intrusive_ptr(intrusive_ptr<U>&& p) noexcept\n            : ptr{ p.ptr }\n        {\n            p.ptr = nullptr;\n        }\n\n        ~intrusive_ptr() noexcept\n        {\n            if (ptr)\n            {\n                ptr->release();\n            }\n        }\n\n        ROCKET_NODISCARD pointer get() const noexcept\n        {\n            return ptr;\n        }\n\n        pointer detach() noexcept\n        {\n            pointer p = ptr;\n            ptr = nullptr;\n            return p;\n        }\n\n        ROCKET_NODISCARD operator pointer() const noexcept\n        {\n            return ptr;\n        }\n\n        ROCKET_NODISCARD pointer operator->() const noexcept\n        {\n            assert(ptr != nullptr);\n            return ptr;\n        }\n\n        ROCKET_NODISCARD reference operator*() const noexcept\n        {\n            assert(ptr != nullptr);\n            return *ptr;\n        }\n\n        ROCKET_NODISCARD pointer* operator&() noexcept\n        {\n            assert(ptr == nullptr);\n            return &ptr;\n        }\n\n        ROCKET_NODISCARD pointer const* operator&() const noexcept\n        {\n            return &ptr;\n        }\n\n        intrusive_ptr& operator=(pointer p) noexcept\n        {\n            if (p)\n            {\n                p->addref();\n            }\n            pointer o = ptr;\n            ptr = p;\n            if (o)\n            {\n                o->release();\n            }\n            return *this;\n        }\n\n        intrusive_ptr& operator=(std::nullptr_t) noexcept\n        {\n            if (ptr)\n            {\n                ptr->release();\n                ptr = nullptr;\n            }\n            return *this;\n        }\n\n        intrusive_ptr& operator=(intrusive_ptr const& p) noexcept\n        {\n            return (*this = p.ptr);\n        }\n\n        intrusive_ptr& operator=(intrusive_ptr&& p) noexcept\n        {\n            if (ptr)\n            {\n                ptr->release();\n            }\n            ptr = p.ptr;\n            p.ptr = nullptr;\n            return *this;\n        }\n\n        template <class U>\n        intrusive_ptr& operator=(intrusive_ptr<U> const& p) noexcept\n        {\n            return (*this = p.ptr);\n        }\n\n        template <class U>\n        intrusive_ptr& operator=(intrusive_ptr<U>&& p) noexcept\n        {\n            if (ptr)\n            {\n                ptr->release();\n            }\n            ptr = p.ptr;\n            p.ptr = nullptr;\n            return *this;\n        }\n\n        void swap(pointer* pp) noexcept\n        {\n            pointer p = ptr;\n            ptr = *pp;\n            *pp = p;\n        }\n\n        void swap(intrusive_ptr& p) noexcept\n        {\n            swap(&p.ptr);\n        }\n\n    private:\n        pointer ptr;\n    };\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator==(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() == b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator==(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() == b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator==(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a == b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator!=(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() != b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator!=(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() != b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator!=(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a != b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() < b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() < b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a < b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<=(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() <= b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<=(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() <= b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator<=(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a <= b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() > b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() > b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a > b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>=(intrusive_ptr<T> const& a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a.get() >= b.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>=(intrusive_ptr<T> const& a, U* b) noexcept\n    {\n        return a.get() >= b;\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline bool operator>=(T* a, intrusive_ptr<U> const& b) noexcept\n    {\n        return a >= b.get();\n    }\n\n    template <class T>\n    ROCKET_NODISCARD inline bool operator==(intrusive_ptr<T> const& a, std::nullptr_t) noexcept\n    {\n        return a.get() == nullptr;\n    }\n\n    template <class T>\n    ROCKET_NODISCARD inline bool operator==(std::nullptr_t, intrusive_ptr<T> const& b) noexcept\n    {\n        return nullptr == b.get();\n    }\n\n    template <class T>\n    ROCKET_NODISCARD inline bool operator!=(intrusive_ptr<T> const& a, std::nullptr_t) noexcept\n    {\n        return a.get() != nullptr;\n    }\n\n    template <class T>\n    ROCKET_NODISCARD inline bool operator!=(std::nullptr_t, intrusive_ptr<T> const& b) noexcept\n    {\n        return nullptr != b.get();\n    }\n\n    template <class T>\n    ROCKET_NODISCARD inline T* get_pointer(intrusive_ptr<T> const& p) noexcept\n    {\n        return p.get();\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const& p) noexcept\n    {\n        return intrusive_ptr<T>{ static_cast<T*>(p.get()) };\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const& p) noexcept\n    {\n        return intrusive_ptr<T>{ const_cast<T*>(p.get()) };\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const& p) noexcept\n    {\n        return intrusive_ptr<T>{ dynamic_cast<T*>(p.get()) };\n    }\n\n    template <class T, class U>\n    ROCKET_NODISCARD inline intrusive_ptr<T> reinterpret_pointer_cast(intrusive_ptr<U> const& p) noexcept\n    {\n        return intrusive_ptr<T>{ reinterpret_cast<T*>(p.get()) };\n    }\n\n    struct ref_count final\n    {\n        unsigned long addref() noexcept\n        {\n            return ++count;\n        }\n\n        unsigned long release() noexcept\n        {\n            return --count;\n        }\n\n        ROCKET_NODISCARD unsigned long get() const noexcept\n        {\n            return count;\n        }\n\n    private:\n        unsigned long count{ 0 };\n    };\n\n    struct ref_count_atomic final\n    {\n        unsigned long addref() noexcept\n        {\n            return ++count;\n        }\n\n        unsigned long release() noexcept\n        {\n            return --count;\n        }\n\n        ROCKET_NODISCARD unsigned long get() const noexcept\n        {\n            return count.load(std::memory_order_relaxed);\n        }\n\n    private:\n        std::atomic<unsigned long> count{ 0 };\n    };\n\n    template <class Class, class RefCount = ref_count>\n    struct ref_counted\n    {\n        ref_counted() noexcept = default;\n\n        ref_counted(ref_counted const&) noexcept\n        {\n        }\n\n        ref_counted& operator=(ref_counted const&) noexcept\n        {\n            return *this;\n        }\n\n        void addref() noexcept\n        {\n            count.addref();\n        }\n\n        void release() noexcept\n        {\n            if (count.release() == 0)\n            {\n                delete static_cast<Class*>(this);\n            }\n        }\n\n    protected:\n        ~ref_counted() noexcept = default;\n\n    private:\n        RefCount count{};\n    };\n\n#ifndef ROCKET_NO_STABLE_LIST\n    template <class T>\n    class stable_list final\n    {\n        struct link_element final : ref_counted<link_element>\n        {\n            link_element() noexcept = default;\n\n            ~link_element() noexcept\n            {\n                if (next)\n                {                 // If we have a next element upon destruction\n                    value()->~T();// then this link is used, else it's a dummy\n                }\n            }\n\n            template <class... Args>\n            void construct(Args&&... args) noexcept(noexcept(T{ std::forward<Args>(args)... }))\n            {\n                new (storage()) T{ std::forward<Args>(args)... };\n            }\n\n            T* value() noexcept\n            {\n                return std::launder(static_cast<T*>(storage()));\n            }\n\n            void* storage() noexcept\n            {\n                return static_cast<void*>(&buffer);\n            }\n\n            intrusive_ptr<link_element> next;\n            intrusive_ptr<link_element> prev;\n\n            alignas(T) std::byte buffer[sizeof(T)];\n        };\n\n        intrusive_ptr<link_element> head;\n        intrusive_ptr<link_element> tail;\n\n        std::size_t elements;\n\n    public:\n        template <class U>\n        struct iterator_base final\n        {\n            using iterator_category = std::bidirectional_iterator_tag;\n            using value_type = std::remove_const_t<U>;\n            using difference_type = ptrdiff_t;\n            using reference = U&;\n            using pointer = U*;\n\n            template <class V>\n            friend class stable_list;\n\n            iterator_base() noexcept = default;\n            ~iterator_base() noexcept = default;\n\n            iterator_base(iterator_base const& i) noexcept\n                : element{ i.element }\n            {\n            }\n\n            iterator_base(iterator_base&& i) noexcept\n                : element{ std::move(i.element) }\n            {\n            }\n\n            template <class V>\n            explicit iterator_base(iterator_base<V> const& i) noexcept\n                : element{ i.element }\n            {\n            }\n\n            template <class V>\n            explicit iterator_base(iterator_base<V>&& i) noexcept\n                : element{ std::move(i.element) }\n            {\n            }\n\n            iterator_base& operator=(iterator_base const& i) noexcept\n            {\n                element = i.element;\n                return *this;\n            }\n\n            iterator_base& operator=(iterator_base&& i) noexcept\n            {\n                element = std::move(i.element);\n                return *this;\n            }\n\n            template <class V>\n            iterator_base& operator=(iterator_base<V> const& i) noexcept\n            {\n                element = i.element;\n                return *this;\n            }\n\n            template <class V>\n            iterator_base& operator=(iterator_base<V>&& i) noexcept\n            {\n                element = std::move(i.element);\n                return *this;\n            }\n\n            iterator_base& operator++() noexcept\n            {\n                element = element->next;\n                return *this;\n            }\n\n            iterator_base operator++(int) noexcept\n            {\n                iterator_base i{ *this };\n                ++(*this);\n                return i;\n            }\n\n            iterator_base& operator--() noexcept\n            {\n                element = element->prev;\n                return *this;\n            }\n\n            iterator_base operator--(int) noexcept\n            {\n                iterator_base i{ *this };\n                --(*this);\n                return i;\n            }\n\n            ROCKET_NODISCARD reference operator*() const noexcept\n            {\n                return *element->value();\n            }\n\n            ROCKET_NODISCARD pointer operator->() const noexcept\n            {\n                return element->value();\n            }\n\n            template <class V>\n            ROCKET_NODISCARD bool operator==(iterator_base<V> const& i) const noexcept\n            {\n                return element == i.element;\n            }\n\n            template <class V>\n            ROCKET_NODISCARD bool operator!=(iterator_base<V> const& i) const noexcept\n            {\n                return element != i.element;\n            }\n\n        private:\n            intrusive_ptr<link_element> element;\n\n            iterator_base(link_element* p) noexcept\n                : element{ p }\n            {\n            }\n        };\n\n        using value_type = T;\n        using reference = T&;\n        using pointer = T*;\n        using const_pointer = const T*;\n\n        using size_type = std::size_t;\n        using difference_type = std::ptrdiff_t;\n\n        using iterator = iterator_base<T>;\n        using const_iterator = iterator_base<T const>;\n        using reverse_iterator = std::reverse_iterator<iterator>;\n        using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n\n        stable_list()\n        {\n            init();\n        }\n\n        ~stable_list()\n        {\n            destroy();\n        }\n\n        stable_list(stable_list const& l)\n        {\n            init();\n            insert(end(), l.begin(), l.end());\n        }\n\n        stable_list(stable_list&& l)\n            : head{ std::move(l.head) }\n            , tail{ std::move(l.tail) }\n            , elements{ l.elements }\n        {\n            l.init();\n        }\n\n        stable_list(std::initializer_list<value_type> l)\n        {\n            init();\n            insert(end(), l.begin(), l.end());\n        }\n\n        template <class Iterator>\n        stable_list(Iterator ibegin, Iterator iend)\n        {\n            init();\n            insert(end(), ibegin, iend);\n        }\n\n        explicit stable_list(size_type count, value_type const& value)\n        {\n            init();\n            insert(end(), count, value);\n        }\n\n        explicit stable_list(size_type count)\n        {\n            init();\n            insert(end(), count, value_type{});\n        }\n\n        stable_list& operator=(stable_list const& l)\n        {\n            if (this != &l)\n            {\n                clear();\n                insert(end(), l.begin(), l.end());\n            }\n            return *this;\n        }\n\n        stable_list& operator=(stable_list&& l)\n        {\n            destroy();\n            head = std::move(l.head);\n            tail = std::move(l.tail);\n            elements = l.elements;\n            l.init();\n            return *this;\n        }\n\n        ROCKET_NODISCARD iterator begin() noexcept\n        {\n            return iterator{ head->next };\n        }\n\n        ROCKET_NODISCARD iterator end() noexcept\n        {\n            return iterator{ tail };\n        }\n\n        ROCKET_NODISCARD const_iterator begin() const noexcept\n        {\n            return const_iterator{ head->next };\n        }\n\n        ROCKET_NODISCARD const_iterator end() const noexcept\n        {\n            return const_iterator{ tail };\n        }\n\n        ROCKET_NODISCARD const_iterator cbegin() const noexcept\n        {\n            return const_iterator{ head->next };\n        }\n\n        ROCKET_NODISCARD const_iterator cend() const noexcept\n        {\n            return const_iterator{ tail };\n        }\n\n        ROCKET_NODISCARD reverse_iterator rbegin() noexcept\n        {\n            return reverse_iterator{ end() };\n        }\n\n        ROCKET_NODISCARD reverse_iterator rend() noexcept\n        {\n            return reverse_iterator{ begin() };\n        }\n\n        ROCKET_NODISCARD const_reverse_iterator rbegin() const noexcept\n        {\n            return const_reverse_iterator{ cend() };\n        }\n\n        ROCKET_NODISCARD const_reverse_iterator rend() const noexcept\n        {\n            return const_reverse_iterator{ cbegin() };\n        }\n\n        ROCKET_NODISCARD const_reverse_iterator crbegin() const noexcept\n        {\n            return const_reverse_iterator{ cend() };\n        }\n\n        ROCKET_NODISCARD const_reverse_iterator crend() const noexcept\n        {\n            return const_reverse_iterator{ cbegin() };\n        }\n\n        ROCKET_NODISCARD reference front() noexcept\n        {\n            return *begin();\n        }\n\n        ROCKET_NODISCARD reference back() noexcept\n        {\n            return *rbegin();\n        }\n\n        ROCKET_NODISCARD value_type const& front() const noexcept\n        {\n            return *cbegin();\n        }\n\n        ROCKET_NODISCARD value_type const& back() const noexcept\n        {\n            return *crbegin();\n        }\n\n        ROCKET_NODISCARD bool empty() const noexcept\n        {\n            return cbegin() == cend();\n        }\n\n        void clear() noexcept\n        {\n            erase(begin(), end());\n        }\n\n        void push_front(value_type const& value)\n        {\n            insert(begin(), value);\n        }\n\n        void push_front(value_type&& value)\n        {\n            insert(begin(), std::move(value));\n        }\n\n        void push_back(value_type const& value)\n        {\n            insert(end(), value);\n        }\n\n        void push_back(value_type&& value)\n        {\n            insert(end(), std::move(value));\n        }\n\n        template <class... Args>\n        reference emplace_front(Args&&... args)\n        {\n            return *emplace(begin(), std::forward<Args>(args)...);\n        }\n\n        template <class... Args>\n        reference emplace_back(Args&&... args)\n        {\n            return *emplace(end(), std::forward<Args>(args)...);\n        }\n\n        void pop_front() noexcept\n        {\n            head->next = head->next->next;\n            head->next->prev = head;\n            --elements;\n        }\n\n        void pop_back() noexcept\n        {\n            tail->prev = tail->prev->prev;\n            tail->prev->next = tail;\n            --elements;\n        }\n\n        iterator insert(iterator const& pos, value_type const& value)\n        {\n            return iterator{ make_link(pos.element, value) };\n        }\n\n        iterator insert(iterator const& pos, value_type&& value)\n        {\n            return iterator{ make_link(pos.element, std::move(value)) };\n        }\n\n        template <class Iterator>\n        iterator insert(iterator const& pos, Iterator ibegin, Iterator iend)\n        {\n            iterator iter{ end() };\n            while (ibegin != iend)\n            {\n                iterator tmp{ insert(pos, *ibegin++) };\n                if (iter == end())\n                {\n                    iter = std::move(tmp);\n                }\n            }\n            return iter;\n        }\n\n        iterator insert(iterator const& pos, std::initializer_list<value_type> l)\n        {\n            return insert(pos, l.begin(), l.end());\n        }\n\n        iterator insert(iterator const& pos, size_type count, value_type const& value)\n        {\n            iterator iter{ end() };\n            for (size_type i = 0; i < count; ++i)\n            {\n                iterator tmp{ insert(pos, value) };\n                if (iter == end())\n                {\n                    iter = std::move(tmp);\n                }\n            }\n            return iter;\n        }\n\n        template <class... Args>\n        iterator emplace(iterator const& pos, Args&&... args)\n        {\n            return iterator{ make_link(pos.element, std::forward<Args>(args)...) };\n        }\n\n        void append(value_type const& value)\n        {\n            insert(end(), value);\n        }\n\n        void append(value_type&& value)\n        {\n            insert(end(), std::move(value));\n        }\n\n        template <class Iterator>\n        void append(Iterator ibegin, Iterator iend)\n        {\n            insert(end(), ibegin, iend);\n        }\n\n        void append(std::initializer_list<value_type> l)\n        {\n            insert(end(), std::move(l));\n        }\n\n        void append(size_type count, value_type const& value)\n        {\n            insert(end(), count, value);\n        }\n\n        void assign(size_type count, value_type const& value)\n        {\n            clear();\n            append(count, value);\n        }\n\n        template <class Iterator>\n        void assign(Iterator ibegin, Iterator iend)\n        {\n            clear();\n            append(ibegin, iend);\n        }\n\n        void assign(std::initializer_list<value_type> l)\n        {\n            clear();\n            append(std::move(l));\n        }\n\n        void resize(size_type count)\n        {\n            resize(count, value_type{});\n        }\n\n        void resize(size_type count, value_type const& value)\n        {\n            size_type cursize = size();\n            if (count > cursize)\n            {\n                for (size_type i = cursize; i < count; ++i)\n                {\n                    push_back(value);\n                }\n            }\n            else\n            {\n                for (size_type i = count; i < cursize; ++i)\n                {\n                    pop_back();\n                }\n            }\n        }\n\n        ROCKET_NODISCARD size_type size() const noexcept\n        {\n            return elements;\n        }\n\n        ROCKET_NODISCARD size_type max_size() const noexcept\n        {\n            return std::numeric_limits<size_type>::max();\n        }\n\n        iterator erase(iterator const& pos) noexcept\n        {\n            pos.element->prev->next = pos.element->next;\n            pos.element->next->prev = pos.element->prev;\n            --elements;\n            return iterator{ pos.element->next };\n        }\n\n        iterator erase(iterator const& first, iterator const& last) noexcept\n        {\n            auto link = first.element;\n            while (link != last.element)\n            {\n                auto next = link->next;\n                link->prev = first.element->prev;\n                link->next = last.element;\n                --elements;\n                link = std::move(next);\n            }\n\n            first.element->prev->next = last.element;\n            last.element->prev = first.element->prev;\n            return last;\n        }\n\n        void remove(value_type const& value) noexcept\n        {\n            for (auto itr = begin(); itr != end(); ++itr)\n            {\n                if (*itr == value)\n                {\n                    erase(itr);\n                }\n            }\n        }\n\n        template <class Predicate>\n        void remove_if(Predicate const& pred)\n        {\n            for (auto itr = begin(); itr != end(); ++itr)\n            {\n                if (pred(*itr))\n                {\n                    erase(itr);\n                }\n            }\n        }\n\n        void swap(stable_list& other) noexcept\n        {\n            if (this != &other)\n            {\n                head.swap(other.head);\n                tail.swap(other.tail);\n                std::swap(elements, other.elements);\n            }\n        }\n\n    private:\n        void init()\n        {\n            head = new link_element;\n            tail = new link_element;\n            head->next = tail;\n            tail->prev = head;\n            elements = 0;\n        }\n\n        void destroy()\n        {\n            clear();\n            head->next = nullptr;\n            tail->prev = nullptr;\n        }\n\n        template <class... Args>\n        link_element* make_link(link_element* l, Args&&... args)\n        {\n            intrusive_ptr<link_element> link{ new link_element };\n            link->construct(std::forward<Args>(args)...);\n            link->prev = l->prev;\n            link->next = l;\n            link->prev->next = link;\n            link->next->prev = link;\n            ++elements;\n            return link;\n        }\n    };\n#endif//~ ROCKET_NO_STABLE_LIST\n\n    template <bool ThreadSafe>\n    struct threading_policy\n    {\n        static constexpr bool is_thread_safe = ThreadSafe;\n    };\n\n    using thread_safe_policy = threading_policy<true>;\n    using thread_unsafe_policy = threading_policy<false>;\n\n    namespace detail\n    {\n        template <class>\n        struct expand_signature;\n\n        template <class R, class... Args>\n        struct expand_signature<R(Args...)> final\n        {\n            using return_type = R;\n            using signature_type = R(Args...);\n        };\n\n        template <class Signature>\n        using get_return_type = typename expand_signature<Signature>::return_type;\n\n        struct shared_lock final : ref_counted<shared_lock, ref_count_atomic>\n        {\n            std::mutex mutex;\n        };\n\n        template <class ThreadingPolicy>\n        struct shared_lock_state;\n\n        template <>\n        struct shared_lock_state<thread_unsafe_policy> final\n        {\n            using threading_policy = thread_unsafe_policy;\n\n            constexpr void lock() noexcept\n            {\n            }\n\n            constexpr bool try_lock() noexcept\n            {\n                return true;\n            }\n\n            constexpr void unlock() noexcept\n            {\n            }\n\n            constexpr void swap(shared_lock_state&) noexcept\n            {\n            }\n        };\n\n        template <>\n        struct shared_lock_state<thread_safe_policy> final\n        {\n            using threading_policy = thread_safe_policy;\n\n            shared_lock_state()\n                : lock_primitive{ new shared_lock }\n            {\n            }\n\n            ~shared_lock_state() = default;\n\n            shared_lock_state(shared_lock_state const& s)\n                : lock_primitive{ s.lock_primitive }\n            {\n            }\n\n            shared_lock_state(shared_lock_state&& s)\n                : lock_primitive{ std::move(s.lock_primitive) }\n            {\n                s.lock_primitive = new shared_lock;\n            }\n\n            shared_lock_state& operator=(shared_lock_state const& rhs)\n            {\n                lock_primitive = rhs.lock_primitive;\n                return *this;\n            }\n\n            shared_lock_state& operator=(shared_lock_state&& rhs)\n            {\n                lock_primitive = std::move(rhs.lock_primitive);\n                rhs.lock_primitive = new shared_lock;\n                return *this;\n            }\n\n            void lock()\n            {\n                lock_primitive->mutex.lock();\n            }\n\n            bool try_lock()\n            {\n                return lock_primitive->mutex.try_lock();\n            }\n\n            void unlock()\n            {\n                lock_primitive->mutex.unlock();\n            }\n\n            void swap(shared_lock_state& s) noexcept\n            {\n                lock_primitive.swap(s.lock_primitive);\n            }\n\n            intrusive_ptr<shared_lock> lock_primitive;\n        };\n\n        template <class ThreadingPolicy>\n        struct connection_base;\n\n        template <>\n        struct connection_base<thread_unsafe_policy> : ref_counted<connection_base<thread_unsafe_policy>>\n        {\n            using threading_policy = thread_unsafe_policy;\n\n            virtual ~connection_base() noexcept = default;\n\n            ROCKET_NODISCARD bool is_connected() const noexcept\n            {\n                return prev != nullptr;\n            }\n\n            void disconnect() noexcept\n            {\n                if (prev != nullptr)\n                {\n                    next->prev = prev;\n                    prev->next = next;\n\n                    // To mark a connection as disconnected, just set its prev-link to null but\n                    // leave the next link alive so we can still traverse through the connections\n                    // if the slot gets disconnected during signal emit.\n                    prev = nullptr;\n                }\n            }\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n            ROCKET_NODISCARD std::thread::id get_tid() const noexcept\n            {\n                return std::thread::id{};\n            }\n\n            ROCKET_NODISCARD constexpr bool is_queued() const noexcept\n            {\n                return false;\n            }\n#endif//~ ROCKET_NO_QUEUED_CONNECTIONS\n\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n            void block() noexcept\n            {\n                ++block_count;\n            }\n\n            void unblock() noexcept\n            {\n                if (block_count > 0)\n                {\n                    --block_count;\n                }\n            }\n\n            ROCKET_NODISCARD bool is_blocked() const noexcept\n            {\n                return block_count > 0;\n            }\n\n            unsigned long block_count{ 0 };\n#endif//~ ROCKET_NO_BLOCKING_CONNECTIONS\n\n            intrusive_ptr<connection_base> next;\n            intrusive_ptr<connection_base> prev;\n        };\n\n        template <>\n        struct connection_base<thread_safe_policy> : ref_counted<connection_base<thread_safe_policy>, ref_count_atomic>\n        {\n            using threading_policy = thread_safe_policy;\n\n            virtual ~connection_base() noexcept = default;\n\n            ROCKET_NODISCARD bool is_connected() const noexcept\n            {\n                return prev != nullptr;\n            }\n\n            void disconnect() noexcept\n            {\n                std::scoped_lock<std::mutex> guard{ lock->mutex };\n\n                if (prev != nullptr)\n                {\n                    next->prev = prev;\n                    prev->next = next;\n\n                    // To mark a connection as disconnected, just set its prev-link to null but\n                    // leave the next link alive so we can still traverse through the connections\n                    // if the slot gets disconnected during signal emit.\n                    prev = nullptr;\n                }\n            }\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n            ROCKET_NODISCARD std::thread::id const& get_tid() const noexcept\n            {\n                return thread_id;\n            }\n\n            ROCKET_NODISCARD bool is_queued() const noexcept\n            {\n                return thread_id != std::thread::id{} && thread_id != std::this_thread::get_id();\n            }\n#endif//~ ROCKET_NO_QUEUED_CONNECTIONS\n\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n            void block() noexcept\n            {\n                std::scoped_lock<std::mutex> guard{ lock->mutex };\n                ++block_count;\n            }\n\n            void unblock() noexcept\n            {\n                std::scoped_lock<std::mutex> guard{ lock->mutex };\n                if (block_count > 0)\n                {\n                    --block_count;\n                }\n            }\n\n            ROCKET_NODISCARD bool is_blocked() const noexcept\n            {\n                return (*static_cast<unsigned long const volatile*>(&block_count)) > 0;\n            }\n\n            unsigned long block_count{ 0 };\n#endif//~ ROCKET_NO_BLOCKING_CONNECTIONS\n\n            intrusive_ptr<connection_base> next;\n            intrusive_ptr<connection_base> prev;\n\n            intrusive_ptr<shared_lock> lock;\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n            std::thread::id thread_id;\n#endif\n        };\n\n        template <class ThreadingPolicy, class T>\n        struct functional_connection : connection_base<ThreadingPolicy>\n        {\n            std::function<T> slot;\n        };\n\n#ifndef ROCKET_NO_TIMERS\n        struct timed_connection final : functional_connection<thread_unsafe_policy, void()>\n        {\n            std::chrono::time_point<std::chrono::steady_clock> expires_at;\n            std::chrono::microseconds interval;\n        };\n#endif\n        // Should make sure that this is POD\n        struct thread_local_data final\n        {\n            void* current_connection;\n            bool is_thread_safe_connection;\n            bool emission_aborted;\n        };\n\n        ROCKET_NODISCARD inline thread_local_data* get_thread_local_data() noexcept\n        {\n            static ROCKET_THREAD_LOCAL thread_local_data th;\n            return &th;\n        }\n\n        struct connection_scope final\n        {\n            connection_scope(void* base, bool is_thread_safe, thread_local_data* th) noexcept\n                : th{ th }\n                , prev{ th->current_connection }\n                , prevThreadSafe{ th->is_thread_safe_connection }\n            {\n                th->current_connection = base;\n                th->is_thread_safe_connection = is_thread_safe;\n            }\n\n            ~connection_scope() noexcept\n            {\n                th->current_connection = prev;\n                th->is_thread_safe_connection = prevThreadSafe;\n            }\n\n            thread_local_data* th;\n            void* prev;\n            bool prevThreadSafe;\n        };\n\n        struct abort_scope final\n        {\n            abort_scope(thread_local_data* th) noexcept\n                : th{ th }\n                , prev{ th->emission_aborted }\n            {\n                th->emission_aborted = false;\n            }\n\n            ~abort_scope() noexcept\n            {\n                th->emission_aborted = prev;\n            }\n\n            thread_local_data* th;\n            bool prev;\n        };\n\n#ifndef ROCKET_NO_SMARTPOINTER_EXTENSIONS\n        template <class Instance, class Class, class R, class... Args>\n        struct weak_mem_fn final\n        {\n            explicit weak_mem_fn(std::weak_ptr<Instance> c, R (Class::*method)(Args...))\n                : weak{ std::move(c) }\n                , method{ method }\n            {\n            }\n\n            template <class... Args1>\n            auto operator()(Args1&&... args) const\n            {\n                if constexpr (std::is_void_v<R>)\n                {\n                    if (auto strong = weak.lock())\n                    {\n                        (strong.get()->*method)(std::forward<Args1>(args)...);\n                    }\n                }\n                else\n                {\n                    if (auto strong = weak.lock())\n                    {\n                        return optional<R>{ (strong.get()->*method)(std::forward<Args1>(args)...) };\n                    }\n                    return optional<R>{};\n                }\n            }\n\n        private:\n            std::weak_ptr<Instance> weak;\n            R (Class::*method)(Args...);\n        };\n\n        template <class Instance, class Class, class R, class... Args>\n        struct shared_mem_fn final\n        {\n            explicit shared_mem_fn(std::shared_ptr<Instance> c, R (Class::*method)(Args...))\n                : shared{ std::move(c) }\n                , method{ method }\n            {\n            }\n\n            template <class... Args1>\n            R operator()(Args1&&... args) const\n            {\n                return (shared.get()->*method)(std::forward<Args1>(args)...);\n            }\n\n        private:\n            std::shared_ptr<Instance> shared;\n            R (Class::*method)(Args...);\n        };\n#endif//~ ROCKET_NO_SMARTPOINTER_EXTENSIONS\n    } // namespace detail\n\n#ifndef ROCKET_NO_SMARTPOINTER_EXTENSIONS\n    template <class Instance, class Class, class R, class... Args>\n    inline auto bind_weak_ptr(std::weak_ptr<Instance> c, R (Class::*method)(Args...))\n    {\n        return detail::weak_mem_fn<Instance, Class, R, Args...>{ std::move(c), method };\n    }\n\n    template <class Instance, class Class, class R, class... Args>\n    inline auto bind_weak_ptr(std::shared_ptr<Instance> c, R (Class::*method)(Args...))\n    {\n        return detail::weak_mem_fn<Instance, Class, R, Args...>{ std::move(c), method };\n    }\n\n    template <class Instance, class Class, class R, class... Args>\n    inline auto bind_shared_ptr(std::shared_ptr<Instance> c, R (Class::*method)(Args...))\n    {\n        return detail::shared_mem_fn<Instance, Class, R, Args...>{ std::move(c), method };\n    }\n#endif\n\n    struct connection\n    {\n        connection() noexcept\n            : base{ nullptr }\n            , is_thread_safe{ false }\n        {\n        }\n\n        ~connection() noexcept\n        {\n            release();\n        }\n\n        connection(connection&& rhs) noexcept\n            : base{ rhs.base }\n            , is_thread_safe{ rhs.is_thread_safe }\n        {\n            rhs.base = nullptr;\n            rhs.is_thread_safe = false;\n        }\n\n        connection(connection const& rhs) noexcept\n            : base{ rhs.base }\n            , is_thread_safe{ rhs.is_thread_safe }\n        {\n            addref();\n        }\n\n        explicit connection(void* base, bool is_thread_safe) noexcept\n            : base{ base }\n            , is_thread_safe{ is_thread_safe }\n        {\n            addref();\n        }\n\n        connection& operator=(connection&& rhs) noexcept\n        {\n            release();\n            base = rhs.base;\n            is_thread_safe = rhs.is_thread_safe;\n            rhs.base = nullptr;\n            rhs.is_thread_safe = false;\n            return *this;\n        }\n\n        connection& operator=(connection const& rhs) noexcept\n        {\n            if (this != &rhs)\n            {\n                release();\n                base = rhs.base;\n                is_thread_safe = rhs.is_thread_safe;\n                addref();\n            }\n            return *this;\n        }\n\n        ROCKET_NODISCARD bool operator==(connection const& rhs) const noexcept\n        {\n            return base == rhs.base && is_thread_safe == rhs.is_thread_safe;\n        }\n\n        ROCKET_NODISCARD bool operator!=(connection const& rhs) const noexcept\n        {\n            return base != rhs.base || is_thread_safe != rhs.is_thread_safe;\n        }\n\n        ROCKET_NODISCARD explicit operator bool() const noexcept\n        {\n            return is_connected();\n        }\n\n        ROCKET_NODISCARD bool is_connected() const noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    return std::launder(safe)->is_connected();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    return std::launder(unsafe)->is_connected();\n                }\n            }\n            return false;\n        }\n\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n        ROCKET_NODISCARD bool is_blocked() const noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    return std::launder(safe)->is_blocked();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    return std::launder(unsafe)->is_blocked();\n                }\n            }\n            return false;\n        }\n\n        void block() noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    std::launder(safe)->block();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    std::launder(unsafe)->block();\n                }\n            }\n        }\n\n        void unblock() noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    std::launder(safe)->unblock();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    std::launder(unsafe)->unblock();\n                }\n            }\n        }\n#endif//~ ROCKET_NO_BLOCKING_CONNECTIONS\n\n        void disconnect() noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    std::launder(safe)->disconnect();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    std::launder(unsafe)->disconnect();\n                }\n\n                release();\n            }\n        }\n\n        void swap(connection& other) noexcept\n        {\n            if (this != &other)\n            {\n                void* tmp_base{ base };\n                bool tmp_is_thread_safe{ is_thread_safe };\n                base = other.base;\n                is_thread_safe = other.is_thread_safe;\n                other.base = tmp_base;\n                other.is_thread_safe = tmp_is_thread_safe;\n            }\n        }\n\n    private:\n        void* base;\n        bool is_thread_safe;\n\n        void addref() noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    std::launder(safe)->addref();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    std::launder(unsafe)->addref();\n                }\n            }\n        }\n\n        void release() noexcept\n        {\n            if (base != nullptr)\n            {\n                if (is_thread_safe)\n                {\n                    auto safe{ static_cast<detail::connection_base<thread_safe_policy>*>(base) };\n                    std::launder(safe)->release();\n                }\n                else\n                {\n                    auto unsafe{ static_cast<detail::connection_base<thread_unsafe_policy>*>(base) };\n                    std::launder(unsafe)->release();\n                }\n\n                base = nullptr;\n                is_thread_safe = false;\n            }\n        }\n    };\n\n    struct scoped_connection final : connection\n    {\n        scoped_connection() noexcept = default;\n\n        ~scoped_connection() noexcept\n        {\n            disconnect();\n        }\n\n        scoped_connection(connection const& rhs) noexcept\n            : connection{ rhs }\n        {\n        }\n\n        scoped_connection(connection&& rhs) noexcept\n            : connection{ std::move(rhs) }\n        {\n        }\n\n        scoped_connection(scoped_connection&& rhs) noexcept\n            : connection{ std::move(rhs) }\n        {\n        }\n\n        scoped_connection& operator=(connection&& rhs) noexcept\n        {\n            disconnect();\n\n            connection::operator=(std::move(rhs));\n            return *this;\n        }\n\n        scoped_connection& operator=(scoped_connection&& rhs) noexcept\n        {\n            disconnect();\n\n            connection::operator=(std::move(rhs));\n            return *this;\n        }\n\n        scoped_connection& operator=(connection const& rhs) noexcept\n        {\n            disconnect();\n\n            connection::operator=(rhs);\n            return *this;\n        }\n\n    private:\n        scoped_connection(scoped_connection const&) = delete;\n\n        scoped_connection& operator=(scoped_connection const&) = delete;\n    };\n\n    struct scoped_connection_container final\n    {\n        scoped_connection_container() = default;\n        ~scoped_connection_container() = default;\n\n        scoped_connection_container(scoped_connection_container&& s)\n            : connections{ std::move(s.connections) }\n        {\n        }\n\n        scoped_connection_container& operator=(scoped_connection_container&& rhs)\n        {\n            connections = std::move(rhs.connections);\n            return *this;\n        }\n\n        scoped_connection_container(std::initializer_list<connection> list)\n        {\n            append(list);\n        }\n\n        void append(connection const& conn)\n        {\n            connections.push_front(scoped_connection{ conn });\n        }\n\n        void append(std::initializer_list<connection> list)\n        {\n            for (auto const& connection : list)\n            {\n                append(connection);\n            }\n        }\n\n        scoped_connection_container& operator+=(connection const& conn)\n        {\n            append(conn);\n            return *this;\n        }\n\n        scoped_connection_container& operator+=(std::initializer_list<connection> list)\n        {\n            for (auto const& connection : list)\n            {\n                append(connection);\n            }\n            return *this;\n        }\n\n        void disconnect() noexcept\n        {\n            connections.clear();\n        }\n\n    private:\n        scoped_connection_container(scoped_connection_container const&) = delete;\n        scoped_connection_container& operator=(scoped_connection_container const&) = delete;\n\n        std::forward_list<scoped_connection> connections;\n    };\n\n    struct trackable\n    {\n        void add_tracked_connection(connection const& conn)\n        {\n            container.append(conn);\n        }\n\n        void disconnect_tracked_connections() noexcept\n        {\n            container.disconnect();\n        }\n\n    private:\n        scoped_connection_container container;\n    };\n\n    ROCKET_NODISCARD inline connection current_connection() noexcept\n    {\n        auto th = detail::get_thread_local_data();\n        return connection{ th->current_connection, th->is_thread_safe_connection };\n    }\n\n    inline void abort_emission() noexcept\n    {\n        detail::get_thread_local_data()->emission_aborted = true;\n    }\n\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n    struct scoped_connection_blocker final\n    {\n        scoped_connection_blocker(connection c) noexcept\n            : conn{ std::move(c) }\n        {\n            conn.block();\n        }\n\n        ~scoped_connection_blocker() noexcept\n        {\n            conn.unblock();\n        }\n\n    private:\n        scoped_connection_blocker(scoped_connection_blocker const&) = delete;\n        scoped_connection_blocker& operator=(scoped_connection_blocker const&) = delete;\n\n        connection conn;\n    };\n#endif//~ ROCKET_NO_BLOCKING_CONNECTIONS\n\n    namespace detail\n    {\n#ifndef ROCKET_NO_TIMERS\n        struct timer_queue final\n        {\n            using slot_type = std::function<void()>;\n\n            timer_queue()\n            {\n                init();\n            }\n\n            ~timer_queue() noexcept\n            {\n                destroy();\n            }\n\n            timer_queue(timer_queue&& q)\n                : head{ std::move(q.head) }\n                , tail{ std::move(q.tail) }\n            {\n                q.init();\n            }\n\n            timer_queue(timer_queue const& q)\n            {\n                init();\n                copy(q);\n            }\n\n            timer_queue& operator=(timer_queue&& rhs)\n            {\n                destroy();\n                head = std::move(rhs.head);\n                tail = std::move(rhs.tail);\n                rhs.init();\n                return *this;\n            }\n\n            timer_queue& operator=(timer_queue const& rhs)\n            {\n                if (this != &rhs)\n                {\n                    clear();\n                    copy(rhs);\n                }\n                return *this;\n            }\n\n            template <class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(slot_type slot, std::chrono::duration<Rep, Period> const& interval)\n            {\n                assert(slot != nullptr);\n\n                auto expires_at = std::chrono::steady_clock::now() + interval;\n                auto interval_microsecs = std::chrono::duration_cast<std::chrono::microseconds>(interval);\n                connection_base* base\n                    = make_link(tail, std::move(slot), std::move(expires_at), std::move(interval_microsecs));\n                return connection{ static_cast<void*>(base), false };\n            }\n\n            template <auto Method, class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(std::chrono::duration<Rep, Period> const& interval)\n            {\n                return set_interval<Rep, Period>([] { (*Method)(); }, interval);\n            }\n\n            template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(\n                Instance& object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& interval)\n            {\n                connection c{ set_interval<Rep, Period>([&object, method] { (object.*method)(); }, interval) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable&>(object).add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(Instance& object, std::chrono::duration<Rep, Period> const& interval)\n            {\n                connection c{ set_interval<Rep, Period>([&object] { (object.*Method)(); }, interval) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable&>(object).add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(\n                Instance* object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& interval)\n            {\n                connection c{ set_interval<Rep, Period>([object, method] { (object->*method)(); }, interval) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable*>(object)->add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n            connection set_interval(Instance* object, std::chrono::duration<Rep, Period> const& interval)\n            {\n                connection c{ set_interval<Rep, Period>([object] { (object->*Method)(); }, interval) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable*>(object)->add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(slot_type slot, std::chrono::duration<Rep, Period> const& timeout)\n            {\n                assert(slot != nullptr);\n\n                auto expires_at = std::chrono::steady_clock::now() + timeout;\n                connection_base* base\n                    = make_link(tail, std::move(slot), std::move(expires_at), std::chrono::microseconds(-1));\n                return connection{ static_cast<void*>(base), false };\n            }\n\n            template <auto Method, class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(std::chrono::duration<Rep, Period> const& timeout)\n            {\n                return set_timeout<Rep, Period>([] { (*Method)(); }, timeout);\n            }\n\n            template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(\n                Instance& object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& timeout)\n            {\n                connection c{ set_timeout<Rep, Period>([&object, method] { (object.*method)(); }, timeout) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable&>(object).add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(Instance& object, std::chrono::duration<Rep, Period> const& timeout)\n            {\n                connection c{ set_timeout<Rep, Period>([&object] { (object.*Method)(); }, timeout) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable&>(object).add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(\n                Instance* object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& timeout)\n            {\n                connection c{ set_timeout<Rep, Period>([object, method] { (object->*method)(); }, timeout) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable*>(object)->add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n            connection set_timeout(Instance* object, std::chrono::duration<Rep, Period> const& timeout)\n            {\n                connection c{ set_timeout<Rep, Period>([object] { (object->*Method)(); }, timeout) };\n                if constexpr (std::is_convertible_v<Instance*, trackable*>)\n                {\n                    static_cast<trackable*>(object)->add_tracked_connection(c);\n                }\n                return c;\n            }\n\n            void clear() noexcept\n            {\n                intrusive_ptr<connection_base> current{ head->next };\n                while (current != tail)\n                {\n                    intrusive_ptr<connection_base> next{ current->next };\n                    current->next = tail;\n                    current->prev = nullptr;\n                    current = std::move(next);\n                }\n\n                head->next = tail;\n                tail->prev = head;\n            }\n\n            void swap(timer_queue& other) noexcept\n            {\n                if (this != &other)\n                {\n                    head.swap(other.head);\n                    tail.swap(other.tail);\n                }\n            }\n\n            bool dispatch(std::chrono::time_point<std::chrono::steady_clock> execute_until)\n            {\n#    ifndef ROCKET_NO_EXCEPTIONS\n                bool error{ false };\n#    endif\n                bool not_enough_time{ false };\n                std::chrono::time_point<std::chrono::steady_clock> now = std::chrono::steady_clock::now();\n                {\n                    detail::thread_local_data* th{ detail::get_thread_local_data() };\n                    detail::abort_scope ascope{ th };\n\n                    intrusive_ptr<connection_base> current{ head->next };\n                    intrusive_ptr<connection_base> end{ tail };\n\n                    while (current != end)\n                    {\n                        assert(current != nullptr);\n\n                        if (current->prev != nullptr\n#    ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n                            && current->block_count == 0\n#    endif\n                        )\n                            ROCKET_LIKELY\n                            {\n                                detail::connection_scope cscope{ current, false, th };\n\n                                timed_connection* conn\n                                    = std::launder(static_cast<timed_connection*>(static_cast<void*>(current)));\n\n                                if (conn->expires_at <= now)\n                                {\n                                    if (conn->interval.count() < 0)\n                                    {\n                                        conn->disconnect();\n                                    }\n                                    else\n                                    {\n                                        conn->expires_at = now + conn->interval;\n                                    }\n#    ifndef ROCKET_NO_EXCEPTIONS\n                                    try\n                                    {\n#    endif\n                                        conn->slot();\n#    ifndef ROCKET_NO_EXCEPTIONS\n                                    }\n                                    catch (...)\n                                    {\n                                        error = true;\n                                    }\n#    endif\n                                    if (execute_until != std::chrono::time_point<std::chrono::steady_clock>{})\n                                        ROCKET_UNLIKELY\n                                        {\n                                            // Check if we already spent the maximum allowed time executing callbacks\n                                            if (execute_until <= std::chrono::steady_clock::now())\n                                            {\n                                                not_enough_time = true;\n                                                break;\n                                            }\n                                        }\n\n                                    if (th->emission_aborted)\n                                        ROCKET_UNLIKELY\n                                        {\n                                            break;\n                                        }\n                                }\n                            }\n\n                        current = current->next;\n                    }\n                }\n\n#    ifndef ROCKET_NO_EXCEPTIONS\n                if (error)\n                    ROCKET_UNLIKELY\n                    {\n                        throw invocation_slot_error{};\n                    }\n#    endif\n                return not_enough_time;\n            }\n\n        private:\n            using connection_base = detail::connection_base<thread_unsafe_policy>;\n\n            void init()\n            {\n                head = new connection_base;\n                tail = new connection_base;\n                head->next = tail;\n                tail->prev = head;\n            }\n\n            void destroy() noexcept\n            {\n                clear();\n                head->next = nullptr;\n                tail->prev = nullptr;\n            }\n\n            void copy(timer_queue const& q)\n            {\n                intrusive_ptr<connection_base> current{ q.head->next };\n                intrusive_ptr<connection_base> end{ q.tail };\n\n                while (current != end)\n                {\n                    timed_connection* conn = std::launder(static_cast<timed_connection*>(static_cast<void*>(current)));\n\n                    make_link(tail, conn->slot, conn->expires_at, conn->interval);\n                    current = current->next;\n                }\n            }\n\n            timed_connection* make_link(\n                connection_base* l,\n                slot_type slot,\n                std::chrono::time_point<std::chrono::steady_clock> expires_at,\n                std::chrono::microseconds interval)\n            {\n                intrusive_ptr<timed_connection> link{ new timed_connection };\n                link->slot = std::move(slot);\n                link->expires_at = std::move(expires_at);\n                link->interval = std::move(interval);\n                link->prev = l->prev;\n                link->next = l;\n                link->prev->next = link;\n                link->next->prev = link;\n                return link;\n            }\n\n            intrusive_ptr<connection_base> head;\n            intrusive_ptr<connection_base> tail;\n        };\n\n        inline timer_queue* get_timer_queue() noexcept\n        {\n            static ROCKET_THREAD_LOCAL timer_queue queue;\n            return &queue;\n        }\n\n#endif//~ ROCKET_NO_TIMERS\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n        struct call_queue final\n        {\n            void put(std::thread::id tid, std::packaged_task<void()> task)\n            {\n                std::scoped_lock<std::mutex> guard{ mutex };\n                queue[tid].emplace_back(std::move(task));\n            }\n\n            bool dispatch(std::chrono::time_point<std::chrono::steady_clock> execute_until)\n            {\n                std::thread::id tid = std::this_thread::get_id();\n                std::deque<std::packaged_task<void()>> thread_queue;\n\n                {\n                    std::scoped_lock<std::mutex> guard{ mutex };\n\n                    auto iterator = queue.find(tid);\n                    if (iterator != queue.end())\n                    {\n                        thread_queue.swap(iterator->second);\n                        queue.erase(iterator);\n                    }\n                }\n\n                auto itr = thread_queue.begin();\n                auto end = thread_queue.end();\n\n                while (itr != end)\n                {\n                    (itr++)->operator()();\n\n                    if (execute_until != std::chrono::time_point<std::chrono::steady_clock>{})\n                        ROCKET_UNLIKELY\n                        {\n                            // check if we already spent the maximum allowed time executing callbacks\n                            if (execute_until <= std::chrono::steady_clock::now())\n                            {\n                                break;\n                            }\n                        }\n                }\n\n                if (itr != end)\n                    ROCKET_UNLIKELY\n                    {\n                        // readd unfinished work to the queue\n                        auto rbegin = std::make_reverse_iterator(end);\n                        auto rend = std::make_reverse_iterator(itr);\n\n                        std::scoped_lock<std::mutex> guard{ mutex };\n                        std::deque<std::packaged_task<void()>>& original_queue = queue[tid];\n\n                        for (auto it = rbegin; it != rend; ++it)\n                        {\n                            original_queue.push_front(std::move(*it));\n                        }\n                    }\n                return itr != end;\n            }\n\n        private:\n            std::mutex mutex;\n            std::unordered_map<std::thread::id, std::deque<std::packaged_task<void()>>> queue;\n        };\n\n        inline call_queue* get_call_queue() noexcept\n        {\n            static call_queue queue;\n            return &queue;\n        }\n\n        template <class T>\n        struct decay\n        {\n            typedef typename std::remove_reference<T>::type U;\n            typedef typename std::conditional<\n                std::is_array<U>::value,\n                typename std::remove_extent<U>::type*,\n                typename std::conditional<\n                    std::is_function<U>::value,\n                    typename std::add_pointer<U>::type,\n                    typename std::conditional<\n                        std::is_const<U>::value || !std::is_reference<T>::value,\n                        typename std::remove_cv<U>::type,\n                        T>::type>::type>::type type;\n        };\n\n        template <class T>\n        struct unwrap_refwrapper\n        {\n            using type = T;\n        };\n\n        template <class T>\n        struct unwrap_refwrapper<std::reference_wrapper<T>>\n        {\n            using type = T&;\n        };\n\n        template <class T>\n        using special_decay_t = typename unwrap_refwrapper<typename decay<T>::type>::type;\n\n        // This make_tuple implementation is different from std::make_tuple.\n        // This one preserves non-const references as actual reference values.\n        // However const references will be stored by value.\n\n        // make_tuple(int const&) => tuple<int>\n        // make_tuple(int&) => tuple<int&>\n\n        template <class... Types>\n        ROCKET_NODISCARD auto make_tuple(Types&&... args)\n        {\n            return std::tuple<special_decay_t<Types>...>(std::forward<Types>(args)...);\n        }\n#endif//~ ROCKET_NO_QUEUED_CONNECTIONS\n    } // namespace detail\n\n#if !defined(ROCKET_NO_TIMERS) || !defined(ROCKET_NO_QUEUED_CONNECTIONS)\n    template <class Rep, class Period>\n    inline void dispatch_queued_calls(std::chrono::duration<Rep, Period> const& max_time_to_execute)\n    {\n        std::chrono::time_point<std::chrono::steady_clock> execute_until{};\n        if (max_time_to_execute.count() > 0)\n            ROCKET_UNLIKELY\n            {\n                execute_until = std::chrono::steady_clock::now() + max_time_to_execute;\n            }\n#    ifndef ROCKET_NO_TIMERS\n        bool not_enough_time = detail::get_timer_queue()->dispatch(execute_until);\n        if (not_enough_time)\n            ROCKET_UNLIKELY\n            {\n                return;\n            }\n#    endif\n#    ifndef ROCKET_NO_QUEUED_CONNECTIONS\n        detail::get_call_queue()->dispatch(execute_until);\n#    endif\n    }\n\n    inline void dispatch_queued_calls()\n    {\n        dispatch_queued_calls(std::chrono::microseconds::zero());\n    }\n#endif\n\n#ifndef ROCKET_NO_TIMERS\n    template <class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(std::function<void()> slot, std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Rep, Period>(std::move(slot), interval);\n    }\n\n    template <auto Method, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Method, Rep, Period>(interval);\n    }\n\n    template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(\n        Instance& object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Instance, Class, R, Rep, Period>(\n            object, method, interval);\n    }\n\n    template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(Instance& object, std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Method, Instance, Rep, Period>(object, interval);\n    }\n\n    template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(\n        Instance* object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Instance, Class, R, Rep, Period>(\n            object, method, interval);\n    }\n\n    template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_interval(Instance* object, std::chrono::duration<Rep, Period> const& interval)\n    {\n        return detail::get_timer_queue()->template set_interval<Method, Instance, Rep, Period>(object, interval);\n    }\n\n    template <class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(std::function<void()> slot, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Rep, Period>(std::move(slot), timeout);\n    }\n\n    template <auto Method, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method, Rep, Period>(timeout);\n    }\n\n    template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(\n        Instance& object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Instance, Class, R, Rep, Period>(\n            object, method, timeout);\n    }\n\n    template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(Instance& object, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method, Instance, Rep, Period>(object, timeout);\n    }\n\n    template <class Instance, class Class, class R, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(\n        Instance* object, R (Class::*method)(), std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Instance, Class, R, Rep, Period>(\n            object, method, timeout);\n    }\n\n    template <auto Method, class Instance, class Rep = unsigned long, class Period = std::milli>\n    inline connection set_timeout(Instance* object, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method, Instance, Rep, Period>(object, timeout);\n    }\n\n    // Overloads for milliseconds\n    inline connection set_interval(std::function<void()> slot, unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<>(\n            std::move(slot), std::chrono::milliseconds(interval_ms));\n    }\n\n    template <auto Method>\n    inline connection set_interval(unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<Method>(std::chrono::milliseconds(interval_ms));\n    }\n\n    template <class Instance, class Class, class R>\n    inline connection set_interval(Instance& object, R (Class::*method)(), unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<Instance, Class, R>(\n            object, method, std::chrono::milliseconds(interval_ms));\n    }\n\n    template <auto Method, class Instance>\n    inline connection set_interval(Instance& object, unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<Method, Instance>(\n            object, std::chrono::milliseconds(interval_ms));\n    }\n\n    template <class Instance, class Class, class R>\n    inline connection set_interval(Instance* object, R (Class::*method)(), unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<Instance, Class, R>(\n            object, method, std::chrono::milliseconds(interval_ms));\n    }\n\n    template <auto Method, class Instance>\n    inline connection set_interval(Instance* object, unsigned long interval_ms)\n    {\n        return detail::get_timer_queue()->template set_interval<Method, Instance>(\n            object, std::chrono::milliseconds(interval_ms));\n    }\n\n    inline connection set_timeout(std::function<void()> slot, unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<>(\n            std::move(slot), std::chrono::milliseconds(timeout_ms));\n    }\n\n    template <auto Method>\n    inline connection set_timeout(unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method>(std::chrono::milliseconds(timeout_ms));\n    }\n\n    template <class Instance, class Class, class R>\n    inline connection set_timeout(Instance& object, R (Class::*method)(), unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<Instance, Class, R>(\n            object, method, std::chrono::milliseconds(timeout_ms));\n    }\n\n    template <auto Method, class Instance>\n    inline connection set_timeout(Instance& object, unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method, Instance>(\n            object, std::chrono::milliseconds(timeout_ms));\n    }\n\n    template <class Instance, class Class, class R>\n    inline connection set_timeout(Instance* object, R (Class::*method)(), unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<Instance, Class, R>(\n            object, method, std::chrono::milliseconds(timeout_ms));\n    }\n\n    template <auto Method, class Instance>\n    inline connection set_timeout(Instance* object, unsigned long timeout_ms)\n    {\n        return detail::get_timer_queue()->template set_timeout<Method, Instance>(\n            object, std::chrono::milliseconds(timeout_ms));\n    }\n\n    inline void clear_timers() noexcept\n    {\n        detail::get_timer_queue()->clear();\n    }\n#endif//~ ROCKET_NO_TIMERS\n\n    template <class T>\n    struct default_collector final : last<optional<T>>\n    {\n    };\n\n    template <>\n    struct default_collector<void>\n    {\n        using value_type = void;\n        using result_type = void;\n\n        void operator()() noexcept\n        {\n            /* do nothing for void types */\n        }\n\n        void result() noexcept\n        {\n            /* do nothing for void types */\n        }\n    };\n\n    enum connection_flags : unsigned int\n    {\n        direct_connection = 0,\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n        queued_connection = 1 << 0,\n#endif\n        connect_as_first_slot = 1 << 1,\n    };\n\n    template <\n        class Signature,\n        class Collector = default_collector<detail::get_return_type<Signature>>,\n        class ThreadingPolicy = thread_unsafe_policy>\n    struct signal;\n\n    template <class Collector, class ThreadingPolicy, class R, class... Args>\n    struct signal<R(Args...), Collector, ThreadingPolicy> final\n    {\n        using threading_policy = ThreadingPolicy;\n        using signature_type = R(Args...);\n        using slot_type = std::function<signature_type>;\n\n        signal()\n        {\n            init();\n        }\n\n        ~signal() noexcept\n        {\n            std::scoped_lock<shared_lock_state> guard{ lock_state };\n            destroy();\n        }\n\n        signal(signal&& s)\n        {\n            static_assert(\n                std::is_same_v<threading_policy, thread_unsafe_policy>,\n                \"Thread safe signals can't be moved or swapped.\");\n\n            head = std::move(s.head);\n            tail = std::move(s.tail);\n            s.init();\n        }\n\n        signal(signal const& s)\n        {\n            init();\n\n            std::scoped_lock<shared_lock_state> guard{ s.lock_state };\n            copy(s);\n        }\n\n        signal& operator=(signal&& rhs)\n        {\n            static_assert(\n                std::is_same_v<threading_policy, thread_unsafe_policy>,\n                \"Thread safe signals can't be moved or swapped.\");\n\n            destroy();\n            head = std::move(rhs.head);\n            tail = std::move(rhs.tail);\n            rhs.init();\n            return *this;\n        }\n\n        signal& operator=(signal const& rhs)\n        {\n            if (this != &rhs)\n            {\n                std::scoped_lock<shared_lock_state, shared_lock_state> guard{ lock_state, rhs.lock_state };\n                clear_without_lock();\n                copy(rhs);\n            }\n            return *this;\n        }\n\n        connection connect(slot_type slot, connection_flags flags = direct_connection)\n        {\n            assert(slot != nullptr);\n\n\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n            std::thread::id tid{};\n\n            if constexpr (std::is_same_v<threading_policy, thread_safe_policy>)\n            {\n                if ((flags & queued_connection) != 0)\n                    ROCKET_UNLIKELY\n                    {\n                        tid = std::this_thread::get_id();\n                    }\n            }\n            else\n            {\n                assert((flags & queued_connection) == 0);\n            }\n#endif\n\n            bool first = (flags & connect_as_first_slot) != 0;\n\n            std::scoped_lock<shared_lock_state> guard{ lock_state };\n            connection_base* base = make_link(\n                first ? head->next : tail,\n                std::move(slot)\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n                    ,\n                tid\n#endif\n            );\n\n            return connection{ static_cast<void*>(base), std::is_same_v<threading_policy, thread_safe_policy> };\n        }\n\n        template <class R1, class... Args1>\n        connection connect(R1 (*method)(Args1...), connection_flags flags = direct_connection)\n        {\n            return connect([method](Args const&... args) { return R((*method)(Args1(args)...)); }, flags);\n        }\n\n        template <auto Method>\n        connection connect(connection_flags flags = direct_connection)\n        {\n            return connect([](Args const&... args) { return R((*Method)(args...)); }, flags);\n        }\n\n        template <class Instance, class Class, class R1, class... Args1>\n        connection connect(Instance& object, R1 (Class::*method)(Args1...), connection_flags flags = direct_connection)\n        {\n            connection c{ connect(\n                [&object, method](Args const&... args) { return R((object.*method)(Args1(args)...)); }, flags) };\n            if constexpr (std::is_convertible_v<Instance*, trackable*>)\n            {\n                static_cast<trackable&>(object).add_tracked_connection(c);\n            }\n            return c;\n        }\n\n        template <auto Method, class Instance>\n        connection connect(Instance& object, connection_flags flags = direct_connection)\n        {\n            connection c{ connect([&object](Args const&... args) { return R((object.*Method)(args...)); }, flags) };\n            if constexpr (std::is_convertible_v<Instance*, trackable*>)\n            {\n                static_cast<trackable&>(object).add_tracked_connection(c);\n            }\n            return c;\n        }\n\n        template <class Instance, class Class, class R1, class... Args1>\n        connection connect(Instance* object, R1 (Class::*method)(Args1...), connection_flags flags = direct_connection)\n        {\n            connection c{ connect(\n                [object, method](Args const&... args) { return R((object->*method)(Args1(args)...)); }, flags) };\n            if constexpr (std::is_convertible_v<Instance*, trackable*>)\n            {\n                static_cast<trackable*>(object)->add_tracked_connection(c);\n            }\n            return c;\n        }\n\n        template <auto Method, class Instance>\n        connection connect(Instance* object, connection_flags flags = direct_connection)\n        {\n            connection c{ connect([object](Args const&... args) { return R((object->*Method)(args...)); }, flags) };\n            if constexpr (std::is_convertible_v<Instance*, trackable*>)\n            {\n                static_cast<trackable*>(object)->add_tracked_connection(c);\n            }\n            return c;\n        }\n\n        connection operator+=(slot_type slot)\n        {\n            return connect(std::move(slot));\n        }\n\n        void clear() noexcept\n        {\n            std::scoped_lock<shared_lock_state> guard{ lock_state };\n            clear_without_lock();\n        }\n\n        void swap(signal& other) noexcept\n        {\n            static_assert(\n                std::is_same_v<threading_policy, thread_unsafe_policy>,\n                \"Thread safe signals can't be moved or swapped.\");\n\n            if (this != &other)\n            {\n                head.swap(other.head);\n                tail.swap(other.tail);\n            }\n        }\n\n        ROCKET_NODISCARD std::size_t get_slot_count() const noexcept\n        {\n            std::size_t count{ 0 };\n            std::scoped_lock<shared_lock_state> guard{ lock_state };\n            intrusive_ptr<connection_base> current{ head->next };\n            intrusive_ptr<connection_base> end{ tail };\n            while (current != end)\n            {\n                if (current->prev != nullptr)\n                {\n                    ++count;\n                }\n                current = current->next;\n            }\n            return count;\n        }\n\n        template <class ValueCollector = Collector>\n        auto invoke(Args const&... args) const\n        {\n#ifndef ROCKET_NO_EXCEPTIONS\n            bool error{ false };\n#endif\n            ValueCollector collector{};\n            {\n                detail::thread_local_data* th{ detail::get_thread_local_data() };\n                detail::abort_scope ascope{ th };\n\n                lock_state.lock();\n\n                intrusive_ptr<connection_base> current{ head->next };\n                intrusive_ptr<connection_base> end{ tail };\n\n                while (current != end)\n                {\n                    assert(current != nullptr);\n\n                    if (current->prev != nullptr\n#ifndef ROCKET_NO_BLOCKING_CONNECTIONS\n                        && current->block_count == 0\n#endif\n                    )\n                        ROCKET_LIKELY\n                        {\n                            detail::connection_scope cscope{ current,\n                                                             std::is_same_v<threading_policy, thread_safe_policy>,\n                                                             th };\n\n                            lock_state.unlock();\n\n                            functional_connection* conn\n                                = std::launder(static_cast<functional_connection*>(static_cast<void*>(current)));\n\n                            if constexpr (std::is_same_v<threading_policy, thread_unsafe_policy>)\n                            {\n#ifndef ROCKET_NO_EXCEPTIONS\n                                try\n                                {\n#endif\n                                    if constexpr (std::is_void_v<R>)\n                                    {\n                                        conn->slot(args...);\n                                        collector();\n                                    }\n                                    else\n                                    {\n                                        collector(conn->slot(args...));\n                                    }\n#ifndef ROCKET_NO_EXCEPTIONS\n                                }\n                                catch (...)\n                                {\n                                    error = true;\n                                }\n#endif\n                            }\n                            else\n                            {\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n                                if (current->is_queued())\n                                    ROCKET_UNLIKELY\n                                    {\n                                        if constexpr (std::is_void_v<R>)\n                                        {\n                                            std::packaged_task<void()> task(\n                                                [current, args = detail::make_tuple(args...)]\n                                                {\n                                                    if (current->is_connected())\n                                                        ROCKET_LIKELY\n                                                        {\n                                                            detail::thread_local_data* th{\n                                                                detail::get_thread_local_data()\n                                                            };\n                                                            detail::connection_scope cscope{\n                                                                current,\n                                                                std::is_same_v<threading_policy, thread_safe_policy>,\n                                                                th\n                                                            };\n\n                                                            functional_connection* conn\n                                                                = std::launder(static_cast<functional_connection*>(\n                                                                    static_cast<void*>(current)));\n\n                                                            std::apply(conn->slot, args);\n                                                        }\n                                                });\n\n                                            detail::get_call_queue()->put(current->get_tid(), std::move(task));\n                                        }\n                                        else\n                                        {\n                                            // If we are calling a queued slot, and our signal requires a return value\n                                            // we actually have to block the thread until the slot was dispatched\n                                            std::packaged_task<void()> task(\n                                                [current, &collector, args = std::forward_as_tuple(args...)]\n                                                {\n                                                    if (current->is_connected())\n                                                        ROCKET_LIKELY\n                                                        {\n                                                            detail::thread_local_data* th{\n                                                                detail::get_thread_local_data()\n                                                            };\n                                                            detail::connection_scope cscope{\n                                                                current,\n                                                                std::is_same_v<threading_policy, thread_safe_policy>,\n                                                                th\n                                                            };\n\n                                                            functional_connection* conn\n                                                                = std::launder(static_cast<functional_connection*>(\n                                                                    static_cast<void*>(current)));\n\n                                                            collector(std::apply(conn->slot, args));\n                                                        }\n                                                });\n\n                                            std::future<void> future{ task.get_future() };\n                                            detail::get_call_queue()->put(current->get_tid(), std::move(task));\n#    ifndef ROCKET_NO_EXCEPTIONS\n                                            try\n                                            {\n#    endif\n                                                future.get();\n#    ifndef ROCKET_NO_EXCEPTIONS\n                                            }\n                                            catch (...)\n                                            {\n                                                error = true;\n                                            }\n#    endif\n                                        }\n                                    }\n                                else\n#endif//~ ROCKET_NO_QUEUED_CONNECTIONS\n                                {\n#ifndef ROCKET_NO_EXCEPTIONS\n                                    try\n                                    {\n#endif\n                                        if constexpr (std::is_void_v<R>)\n                                        {\n                                            conn->slot(args...);\n                                            collector();\n                                        }\n                                        else\n                                        {\n                                            collector(conn->slot(args...));\n                                        }\n#ifndef ROCKET_NO_EXCEPTIONS\n                                    }\n                                    catch (...)\n                                    {\n                                        error = true;\n                                    }\n#endif\n                                }\n                            }\n\n                            lock_state.lock();\n\n                            if (th->emission_aborted)\n                                ROCKET_UNLIKELY\n                                {\n                                    break;\n                                }\n                        }\n\n                    current = current->next;\n                }\n\n                lock_state.unlock();\n            }\n\n#ifndef ROCKET_NO_EXCEPTIONS\n            if (error)\n                ROCKET_UNLIKELY\n                {\n                    throw invocation_slot_error{};\n                }\n#endif\n            return collector.result();\n        }\n\n        auto operator()(Args const&... args) const\n        {\n            return invoke(args...);\n        }\n\n    private:\n        using shared_lock_state = detail::shared_lock_state<threading_policy>;\n        using connection_base = detail::connection_base<threading_policy>;\n        using functional_connection = detail::functional_connection<threading_policy, signature_type>;\n\n        void init()\n        {\n            head = new connection_base;\n            tail = new connection_base;\n            head->next = tail;\n            tail->prev = head;\n        }\n\n        void destroy() noexcept\n        {\n            clear_without_lock();\n            head->next = nullptr;\n            tail->prev = nullptr;\n        }\n\n        void clear_without_lock() noexcept\n        {\n            intrusive_ptr<connection_base> current{ head->next };\n            while (current != tail)\n            {\n                intrusive_ptr<connection_base> next{ current->next };\n                current->next = tail;\n                current->prev = nullptr;\n                current = std::move(next);\n            }\n\n            head->next = tail;\n            tail->prev = head;\n        }\n\n        void copy(signal const& s)\n        {\n            intrusive_ptr<connection_base> current{ s.head->next };\n            intrusive_ptr<connection_base> end{ s.tail };\n\n            while (current != end)\n            {\n                functional_connection* conn\n                    = std::launder(static_cast<functional_connection*>(static_cast<void*>(current)));\n\n                make_link(\n                    tail,\n                    conn->slot\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n                    ,\n                    conn->get_tid()\n#endif\n                );\n                current = current->next;\n            }\n        }\n\n        functional_connection* make_link(\n            connection_base* l,\n            slot_type slot\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n            ,\n            ROCKET_MAYBE_UNUSED std::thread::id tid\n#endif\n        )\n        {\n            intrusive_ptr<functional_connection> link{ new functional_connection };\n\n            if constexpr (std::is_same_v<threading_policy, thread_safe_policy>)\n            {\n                link->lock = lock_state.lock_primitive;\n#ifndef ROCKET_NO_QUEUED_CONNECTIONS\n                link->thread_id = std::move(tid);\n#endif\n            }\n\n            link->slot = std::move(slot);\n            link->prev = l->prev;\n            link->next = l;\n            link->prev->next = link;\n            link->next->prev = link;\n            return link;\n        }\n\n        intrusive_ptr<connection_base> head;\n        intrusive_ptr<connection_base> tail;\n\n        ROCKET_NO_UNIQUE_ADDRESS mutable shared_lock_state lock_state;\n    };\n\n    template <class Signature, class Collector = default_collector<detail::get_return_type<Signature>>>\n    using thread_safe_signal = signal<Signature, Collector, thread_safe_policy>;\n\n    template <class Instance, class Class, class R, class... Args>\n    ROCKET_NODISCARD inline std::function<R(Args...)> slot(Instance& object, R (Class::*method)(Args...))\n    {\n        return [&object, method](Args const&... args) { return (object.*method)(args...); };\n    }\n\n    template <class Instance, class Class, class R, class... Args>\n    ROCKET_NODISCARD inline std::function<R(Args...)> slot(Instance* object, R (Class::*method)(Args...))\n    {\n        return [object, method](Args const&... args) { return (object->*method)(args...); };\n    }\n\n    template <class T>\n    inline void swap(intrusive_ptr<T>& p1, intrusive_ptr<T>& p2) noexcept\n    {\n        p1.swap(p2);\n    }\n\n#ifndef ROCKET_NO_STABLE_LIST\n    template <class T>\n    inline void swap(stable_list<T>& l1, stable_list<T>& l2) noexcept\n    {\n        l1.swap(l2);\n    }\n#endif//~ ROCKET_NO_STABLE_LIST\n\n    inline void swap(connection& c1, connection& c2) noexcept\n    {\n        c1.swap(c2);\n    }\n\n    template <class Signature, class Collector, class ThreadingPolicy>\n    inline void swap(\n        signal<Signature, Collector, ThreadingPolicy>& s1, signal<Signature, Collector, ThreadingPolicy>& s2) noexcept\n    {\n        s1.swap(s2);\n    }\n}// namespace rocket\n\n#endif\n"
  }
]