<commit_before>#include <pthread.h>
#include <string.h>
#include <string>
#include <stdint.h>
#include <unistd.h>
#include <re.h>
#include <vector>

#include "timer.hpp"
#include "uamanager.hpp"
#include "stats_displayer.hpp"
#include "useragent.hpp"
#include "stack.hpp"
#include "logger.hpp"
#include "csv.h"
#include "docopt.h"

static std::vector<UserAgent*> ues;
StatsDisplayer* stats_displayer;

class CallScheduler;
class Cleanup;

static CallScheduler* call_scheduler;
static Cleanup* cleanup_task;
                        
class InitialRegistrar : public RepeatingTimer
{
public:
    InitialRegistrar(uint rps) :
        RepeatingTimer(10), 
        _actual_ues_registered(0),
        _registers_per_sec(rps) {};

    bool act();
    bool everything_registered() { return _actual_ues_registered == ues.size(); }
private:
    uint64_t _actual_ues_registered;
    int _registers_per_sec;
};

class CallScheduler : public RepeatingTimer
{
public:
    CallScheduler(int cps, uint64_t max_calls) :
        RepeatingTimer(10),
        _actual_calls(0),
        _calls_per_sec(cps),
        _max_calls(max_calls) {};

    bool act();
private:
    uint64_t _actual_calls;
    int _calls_per_sec;
    uint64_t _max_calls;
};

class Cleanup : public RepeatingTimer
{
public:
    Cleanup() : RepeatingTimer(1000) {};

    bool act();
};

bool Cleanup::act()
{
    static int times = 0;
    printf("Cleanup running\n");
    if (times == 1)
    {
        for (UserAgent* a : ues)
        {
            a->unregister();
        }
    } else if (times == 2)<commit_msg>Delay before closing SIP stacks to avoid shutdown crashes<commit_after>#include <pthread.h>
#include <string.h>
#include <string>
#include <stdint.h>
#include <unistd.h>
#include <re.h>
#include <vector>

#include "timer.hpp"
#include "uamanager.hpp"
#include "stats_displayer.hpp"
#include "useragent.hpp"
#include "stack.hpp"
#include "logger.hpp"
#include "csv.h"
#include "docopt.h"

static std::vector<UserAgent*> ues;
StatsDisplayer* stats_displayer;

class CallScheduler;
class Cleanup;

static CallScheduler* call_scheduler;
static Cleanup* cleanup_task;
                        
class InitialRegistrar : public RepeatingTimer
{
public:
    InitialRegistrar(uint rps) :
        RepeatingTimer(10), 
        _actual_ues_registered(0),
        _registers_per_sec(rps) {};

    bool act();
    bool everything_registered() { return _actual_ues_registered == ues.size(); }
private:
    uint64_t _actual_ues_registered;
    int _registers_per_sec;
};

class CallScheduler : public RepeatingTimer
{
public:
    CallScheduler(int cps, uint64_t max_calls) :
        RepeatingTimer(10),
        _actual_calls(0),
        _calls_per_sec(cps),
        _max_calls(max_calls) {};

    bool act();
private:
    uint64_t _actual_calls;
    int _calls_per_sec;
    uint64_t _max_calls;
};

class Cleanup : public RepeatingTimer
{
public:
    Cleanup() : RepeatingTimer(1000) {};

    bool act();
};

bool Cleanup::act()
{
    static int times = 0;
    printf("Cleanup running\n");
    if (times == 1)
    {
        for (UserAgent* a : ues)
        {
            a->unregister();
        }
    } else if (times == 12)
{'fraction_non_alphanumeric': 0.11983601387574898, 'fraction_numerical': 0.013560391043834753, 'mean_word_length': 3.3994452149791954, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, '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': '1626464', 'n_tokens_mistral': 1140, 'n_tokens_neox': 1110, 'n_words': 243}