<commit_before>#ifndef THORSANVIL_NISSE_CORE_SERVICE_HANDLER_H
#define THORSANVIL_NISSE_CORE_SERVICE_HANDLER_H

#include "EventUtil.h"
#include "CoRoutine.h"
#include "ThorsNisseCoreSocket/Socket.h"
#include <memory>
#include <functional>

extern "C" void eventCB(ThorsAnvil::Nisse::Core::Service::LibSocketId socketId, short eventType, void* event);

namespace ThorsAnvil
{
    namespace Nisse
    {
        namespace Core
        {
            namespace Service
            {

using EventDeleter  = decltype(&event_free);
using NisseEvent    = std::unique_ptr<LibEvent, EventDeleter>;

class Server;
class HandlerBase
{
    private:
        Server&                             parent;
        NisseEvent                          readEvent;
        NisseEvent                          writeEvent;
        HandlerBase*                        suspended;

    public:
        HandlerBase(Server& parent, LibSocketId socketId, short eventType, double timeout = 0);
        virtual ~HandlerBase();
        void activateEventHandlers(LibSocketId sockId, short eventType);        // The C-Callback point.
                                                                                // Should make this private
        virtual short eventActivate(LibSocketId sockId, short eventType);
        virtual bool  suspendable() = 0;
        void setHandlers(short eventType, TimeVal* timeVal = nullptr);
    protected:
        void dropHandler();
        template<typename H, typename... Args>
        void addHandler(Args&&... args);
        template<typename H, typename... Args>
        void moveHandler(Args&&... args);
    public:
        void dropEvent();
    private:
        virtual void suspend() = 0;
        void resume();
    private:
        friend class Server;
        void setSuspend(HandlerBase& handlerToSuspend);
};

class HandlerNonSuspendable: public HandlerBase
{
    public:
        using HandlerBase::HandlerBase;
        virtual void suspend()      final {throw std::runtime_error("ThorsAnvil::Nisse::HandlerNonSuspendable::suspend: Failed");};
        virtual bool suspendable()  final {return false;}
};

using CoRoutine = ThorsAnvil::Nisse::Core::Service::Context<short>::pull_type;
using Yield     = ThorsAnvil::Nisse::Core::Service::Context<short>::push_type;

class HandlerSuspendable: public HandlerBase
{
    protected:
    Yield*      yield;
    private:
    CoRoutine*  worker;
    short       firstEvent;
    public:
        using HandlerBase::HandlerBase;
        HandlerSuspendable(Server& parent, LibSocketId socketId, short eventType)
            : HandlerSuspendable(parent, socketId, eventType, eventType)
        {}
        HandlerSuspendable(Server& parent, LibSocketId socketId, short eventType, short firstEvent)
            : HandlerBase(parent, socketId, eventType, 0)
            , yield(nullptr)
            , worker(nullptr)
            , firstEvent(firstEvent)
        {}
        virtual void suspend()      final {(*yield)(0);}
        virtual bool suspendable()  final {return true;}
        virtual short eventActivate(LibSocketId /*sockId*/, short /*eventType*/) final
        {
            if (worker == nullptr)
            {
                worker = new CoRoutine([&parentYield = this->yield, &parent = *this, firstEvent = this->firstEvent](Yield& yield)
                    {
                        parentYield = &yield;
                        yield(firstEvent);
                        parent.eventActivateNonBlocking();
                        return 0;
                    });
            }
            if (!(*worker)())<commit_msg>Correct memory management of the worker<commit_after>#ifndef THORSANVIL_NISSE_CORE_SERVICE_HANDLER_H
#define THORSANVIL_NISSE_CORE_SERVICE_HANDLER_H

#include "EventUtil.h"
#include "CoRoutine.h"
#include "ThorsNisseCoreSocket/Socket.h"
#include <memory>
#include <functional>

extern "C" void eventCB(ThorsAnvil::Nisse::Core::Service::LibSocketId socketId, short eventType, void* event);

namespace ThorsAnvil
{
    namespace Nisse
    {
        namespace Core
        {
            namespace Service
            {

using EventDeleter  = decltype(&event_free);
using NisseEvent    = std::unique_ptr<LibEvent, EventDeleter>;

class Server;
class HandlerBase
{
    private:
        Server&                             parent;
        NisseEvent                          readEvent;
        NisseEvent                          writeEvent;
        HandlerBase*                        suspended;

    public:
        HandlerBase(Server& parent, LibSocketId socketId, short eventType, double timeout = 0);
        virtual ~HandlerBase();
        void activateEventHandlers(LibSocketId sockId, short eventType);        // The C-Callback point.
                                                                                // Should make this private
        virtual short eventActivate(LibSocketId sockId, short eventType);
        virtual bool  suspendable() = 0;
        void setHandlers(short eventType, TimeVal* timeVal = nullptr);
    protected:
        void dropHandler();
        template<typename H, typename... Args>
        void addHandler(Args&&... args);
        template<typename H, typename... Args>
        void moveHandler(Args&&... args);
    public:
        void dropEvent();
    private:
        virtual void suspend() = 0;
        void resume();
    private:
        friend class Server;
        void setSuspend(HandlerBase& handlerToSuspend);
};

class HandlerNonSuspendable: public HandlerBase
{
    public:
        using HandlerBase::HandlerBase;
        virtual void suspend()      final {throw std::runtime_error("ThorsAnvil::Nisse::HandlerNonSuspendable::suspend: Failed");};
        virtual bool suspendable()  final {return false;}
};

using CoRoutine = ThorsAnvil::Nisse::Core::Service::Context<short>::pull_type;
using Yield     = ThorsAnvil::Nisse::Core::Service::Context<short>::push_type;

class HandlerSuspendable: public HandlerBase
{
    protected:
    Yield*                      yield;
    private:
    std::unique_ptr<CoRoutine>  worker;
    short                       firstEvent;
    public:
        using HandlerBase::HandlerBase;
        HandlerSuspendable(Server& parent, LibSocketId socketId, short eventType)
            : HandlerSuspendable(parent, socketId, eventType, eventType)
        {}
        HandlerSuspendable(Server& parent, LibSocketId socketId, short eventType, short firstEvent)
            : HandlerBase(parent, socketId, eventType, 0)
            , yield(nullptr)
            , firstEvent(firstEvent)
        {}
        virtual void suspend()      final {(*yield)(0);}
        virtual bool suspendable()  final {return true;}
        virtual short eventActivate(LibSocketId /*sockId*/, short /*eventType*/) final
        {
            if (worker == nullptr)
            {
                worker.reset(new CoRoutine([&parentYield = this->yield, &parent = *this, firstEvent = this->firstEvent](Yield& yield)
                    {
                        parentYield = &yield;
                        yield(firstEvent);
                        parent.eventActivateNonBlocking();
                        return 0;
                    }));
            }
            if (!(*worker)())
{'fraction_non_alphanumeric': 0.09389281262982967, 'fraction_numerical': 0.0016618196925633569, 'mean_word_length': 2.135909683022145, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1751255', 'n_tokens_mistral': 1928, 'n_tokens_neox': 1892, 'n_words': 460}