<commit_before>// scheduler.h - The internal queue class
//
// This is the declaration of the internal scheduler
// class that is part of the implementation of the
// application method for non blocking communication
// between the components and scheduling

#pragma once

// dependencies
#include "../util/timebudget.h"
#include "entity.h"
#include <list>

namespace meisterwerk {
    namespace core {

        class scheduler {
            public:
            // constants
            static const unsigned int PRIORITY_SYSTEMCRITICAL = 0;
            static const unsigned int PRIORITY_TIMECRITICAL   = 1;
            static const unsigned int PRIORITY_HIGH           = 2;
            static const unsigned int PRIORITY_NORMAL         = 3;
            static const unsigned int PRIORITY_LOW            = 4;
            static const unsigned int PRIORITY_LOWEST         = 5;

            // internal types
            protected:
            typedef struct {
                String subscriber;
                String topic;
            } T_SUBSCRIPTION;

            class task {
                public:
                task( entity *_pEnt, unsigned long _minMicros, unsigned int _priority ) {
                    pEnt      = _pEnt;
                    minMicros = _minMicros;
                    priority  = _priority;
                    lastCall  = 0;
                    lateTime  = 0;
                }

                entity *      pEnt;
                unsigned long minMicros;
                unsigned int  priority;
                unsigned long lastCall;
                unsigned long lateTime;

                DBG_ONLY( meisterwerk::util::timebudget msgTime );
                DBG_ONLY( meisterwerk::util::timebudget tskTime );
            };

            typedef task *                    T_PTASK;
            typedef std::list<T_PTASK>        T_TASKLIST;
            typedef std::list<T_SUBSCRIPTION> T_SUBSCRIPTIONLIST;

            // members
            T_TASKLIST         taskList;
            T_SUBSCRIPTIONLIST subscriptionList;

            // methods
            public:
            scheduler() {
                taskList.clear();
                subscriptionList.clear();
                DBG_ONLY( allTime.snap() );
            }

            virtual ~scheduler() {
                for ( auto pTask : taskList ) {
                    delete pTask;
                }
                taskList.clear();
            }

            void loop() {
                // process entity and kernel tasks
                processMsgQueue();

                // XXX: sort tasks according to urgency
                for ( auto pTask : taskList ) {
                    // process message queue
                    processMsgQueue();
                    // process entity and kernel tasks
                    processTask( pTask );
                }
                DBG_ONLY( allTime.shot() );
            }

            // internal methods
            protected:
            void processMsgQueue() {
                DBG_ONLY( msgTime.snap() );
                for ( message *pMsg = message::que.pop(); pMsg != nullptr; pMsg = message::que.pop() ) {
                    switch ( pMsg->type ) {
                    case message::MSG_DIRECT:
                        directMsg( pMsg );
                        break;
                    case message::MSG_PUBLISH:
                        publishMsg( pMsg );
                        break;
                    case message::MSG_SUBSCRIBE:
                        subscribeMsg( pMsg );
                        break;
                    case message::MSG_UNSUBSCRIBE:
                        unsubscribeMsg( pMsg );
                        break;
                    default:
                        DBG( "Unexpected message type: " + String( pMsg->type ) );
                        break;
                    }
                    delete pMsg;
                    DBG_ONLY( msgTime.shot() );
                }
            }

            void processTask( T_PTASK pTask ) {
                unsigned long ticker = micros();
                unsigned long tDelta = meisterwerk::util::timebudget::delta( pTask->lastCall, ticker );
                if ( ( pTask->minMicros > 0 ) && ( tDelta >= pTask->minMicros ) ) {
                    DBG_ONLY( tskTime.snap() );
                    DBG_ONLY( pTask->tskTime.snap() );

                    pTask->pEnt->onLoop( ticker );<commit_msg>Yield() and HW-Watchdog feeding<commit_after>// scheduler.h - The internal queue class
//
// This is the declaration of the internal scheduler
// class that is part of the implementation of the
// application method for non blocking communication
// between the components and scheduling

#pragma once

// dependencies
#include "../util/timebudget.h"
#include "entity.h"
#include <list>

namespace meisterwerk {
    namespace core {

        class scheduler {
            public:
            // constants
            static const unsigned int PRIORITY_SYSTEMCRITICAL = 0;
            static const unsigned int PRIORITY_TIMECRITICAL   = 1;
            static const unsigned int PRIORITY_HIGH           = 2;
            static const unsigned int PRIORITY_NORMAL         = 3;
            static const unsigned int PRIORITY_LOW            = 4;
            static const unsigned int PRIORITY_LOWEST         = 5;

            // internal types
            protected:
            typedef struct {
                String subscriber;
                String topic;
            } T_SUBSCRIPTION;

            class task {
                public:
                task( entity *_pEnt, unsigned long _minMicros, unsigned int _priority ) {
                    pEnt      = _pEnt;
                    minMicros = _minMicros;
                    priority  = _priority;
                    lastCall  = 0;
                    lateTime  = 0;
                }

                entity *      pEnt;
                unsigned long minMicros;
                unsigned int  priority;
                unsigned long lastCall;
                unsigned long lateTime;

                DBG_ONLY( meisterwerk::util::timebudget msgTime );
                DBG_ONLY( meisterwerk::util::timebudget tskTime );
            };

            typedef task *                    T_PTASK;
            typedef std::list<T_PTASK>        T_TASKLIST;
            typedef std::list<T_SUBSCRIPTION> T_SUBSCRIPTIONLIST;

            // members
            T_TASKLIST         taskList;
            T_SUBSCRIPTIONLIST subscriptionList;

            // methods
            public:
            scheduler() {
                taskList.clear();
                subscriptionList.clear();
                DBG_ONLY( allTime.snap() );
                ESP.wdtDisable();
                ESP.wdtEnable( WDTO_8S );
            }

            virtual ~scheduler() {
                for ( auto pTask : taskList ) {
                    delete pTask;
                }
                taskList.clear();
            }

            unsigned long lastYield  = 0;
            unsigned long yieldAfter = 5000; // 5 ms
            void          checkYield() {
                unsigned long curMicros = micros();
                unsigned long tDelta    = meisterwerk::util::timebudget::delta( lastYield, curMicros );
                if ( tDelta > yieldAfter ) {
                    yield();
                    lastYield = micros();
                }
            }

            void loop() {
                // process entity and kernel tasks
                processMsgQueue();

                // XXX: sort tasks according to urgency
                for ( auto pTask : taskList ) {
                    // process message queue
                    processMsgQueue();
                    // process entity and kernel tasks
                    processTask( pTask );
                    checkYield();
                }
                ESP.wdtFeed();
                DBG_ONLY( allTime.shot() );
            }

            // internal methods
            protected:
            void processMsgQueue() {
                DBG_ONLY( msgTime.snap() );
                for ( message *pMsg = message::que.pop(); pMsg != nullptr; pMsg = message::que.pop() ) {
                    switch ( pMsg->type ) {
                    case message::MSG_DIRECT:
                        directMsg( pMsg );
                        break;
                    case message::MSG_PUBLISH:
                        publishMsg( pMsg );
                        break;
                    case message::MSG_SUBSCRIBE:
                        subscribeMsg( pMsg );
                        break;
                    case message::MSG_UNSUBSCRIBE:
                        unsubscribeMsg( pMsg );
                        break;
                    default:
                        DBG( "Unexpected message type: " + String( pMsg->type ) );
                        break;
                    }
                    delete pMsg;
                    checkYield();
                    DBG_ONLY( msgTime.shot() );
                }
            }

            void processTask( T_PTASK pTask ) {
                unsigned long ticker = micros();
                unsigned long tDelta = meisterwerk::util::timebudget::delta( pTask->lastCall, ticker );
                if ( ( pTask->minMicros > 0 ) && ( tDelta >= pTask->minMicros ) ) {
                    DBG_ONLY( tskTime.snap() );
                    DBG_ONLY( pTask->tskTime.snap() );

                    pTask->pEnt->onLoop( ticker );
{'fraction_non_alphanumeric': 0.07608008429926238, 'fraction_numerical': 0.0026343519494204425, 'mean_word_length': 1.098386026973248, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '606089', 'n_tokens_mistral': 2379, 'n_tokens_neox': 2148, 'n_words': 585}