<commit_before>/*
 * Managing background jobs.
 *
 * author: <NAME> <<EMAIL>>
 */

#ifndef BENG_PROXY_BACKGROUND_HXX
#define BENG_PROXY_BACKGROUND_HXX

#include "async.h"

#include <inline/list.h>

/**
 * A job running in the background, which shall be aborted when
 * beng-proxy is shut down.  The job holds a reference to an
 * #async_operation object, which may be used to stop it.
 */
struct BackgroundJob {
    struct list_head siblings;

    struct async_operation_ref async_ref;
};

static inline BackgroundJob *
list_head_to_background_job(struct list_head *head)
{
    const void *p = ((char *)head) - offsetof(BackgroundJob, siblings);
    return (BackgroundJob *)p;
}

/**
 * A container for background jobs.
 */
class BackgroundManager {
    struct list_head jobs;

public:
    BackgroundManager() {
        list_init(&jobs);
    }

    /**
     * Register a job to the manager.
     */
    void Add(BackgroundJob &job) {
        list_add(&job.siblings, &jobs);
    }

    /**
     * Add a background job to the manager, and return its
     * #async_operation_ref.  This is a convenience function.
     */
    struct async_operation_ref *Add2(BackgroundJob &job) {
        Add(job);
        return &job.async_ref;
    }

    /**
     * Leave the job registered in the manager, and reuse its
     * #async_operation_ref for another job iteration.
     */
    struct async_operation_ref *Reuse(BackgroundJob &job) {
        return &job.async_ref;
    }

    /**
     * Unregister a job from the manager.
     */
    void Remove(BackgroundJob &job) {
        list_remove(&job.siblings);
    }

    /**
     * Abort the job and unregister it from the manager.  This function
     * should not be called, it is used internally.
     */
    void AbortInternal(BackgroundJob &job) {
        Remove(job);
        async_abort(&job.async_ref);
    }

    /**
     * Abort all background jobs in the manager.  This is called on
     * shutdown.
     */
    void AbortAll() {
        while (!list_empty(&jobs)) {
            BackgroundJob *job =
                list_head_to_background_job(jobs.next);

            AbortInternal(*job);
        }
    }<commit_msg>background: use class boost::intrusive::list instead of struct list_head<commit_after>/*
 * Managing background jobs.
 *
 * author: <NAME> <<EMAIL>>
 */

#ifndef BENG_PROXY_BACKGROUND_HXX
#define BENG_PROXY_BACKGROUND_HXX

#include "async.h"

#include <boost/intrusive/list.hpp>

/**
 * A job running in the background, which shall be aborted when
 * beng-proxy is shut down.  The job holds a reference to an
 * #async_operation object, which may be used to stop it.
 */
struct BackgroundJob {
    static constexpr auto link_mode = boost::intrusive::normal_link;
    typedef boost::intrusive::link_mode<link_mode> LinkMode;
    typedef boost::intrusive::list_member_hook<LinkMode> SiblingsListHook;
    SiblingsListHook siblings;

    struct async_operation_ref async_ref;
};

/**
 * A container for background jobs.
 */
class BackgroundManager {
    boost::intrusive::list<BackgroundJob,
                           boost::intrusive::member_hook<BackgroundJob,
                                                         BackgroundJob::SiblingsListHook,
                                                         &BackgroundJob::siblings>,
                           boost::intrusive::constant_time_size<false>> jobs;

public:
    /**
     * Register a job to the manager.
     */
    void Add(BackgroundJob &job) {
        jobs.push_front(job);
    }

    /**
     * Add a background job to the manager, and return its
     * #async_operation_ref.  This is a convenience function.
     */
    struct async_operation_ref *Add2(BackgroundJob &job) {
        Add(job);
        return &job.async_ref;
    }

    /**
     * Leave the job registered in the manager, and reuse its
     * #async_operation_ref for another job iteration.
     */
    struct async_operation_ref *Reuse(BackgroundJob &job) {
        return &job.async_ref;
    }

    /**
     * Unregister a job from the manager.
     */
    void Remove(BackgroundJob &job) {
        jobs.erase(jobs.iterator_to(job));
    }

    /**
     * Abort all background jobs in the manager.  This is called on
     * shutdown.
     */
    void AbortAll() {
        jobs.clear_and_dispose([this](BackgroundJob *job){
                async_abort(&job->async_ref);
            });
    }
{'fraction_non_alphanumeric': 0.09979494190020506, 'fraction_numerical': 0.000455684666210982, 'mean_word_length': 2.408385093167702, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2312922', 'n_tokens_mistral': 1306, 'n_tokens_neox': 1283, 'n_words': 358}