<commit_before>#ifndef BITCOIN_THREAD_GROUP_H
#define BITCOIN_THREAD_GROUP_H

#include <atomic>
#include <thread>
#include <vector>


extern std::atomic<bool> shutdown_threads;

class thread_group
{
private:
    std::vector<std::thread> threads;

public:
    void interrupt_all() { shutdown_threads.store(true); }
    template <class Fn, class... Args>
    void create_thread(Fn &&f, Args &&... args)
    {
        threads.push_back(std::thread(f, args...));
    }

    bool empty() { return threads.size() == 0; }
    void join_all()
    {
        for (size_t i = 0; i < threads.size(); i++)
        {
            if (threads[i].joinable())
            {
                threads[i].join();
            }
        }
        threads.clear();
    }
};

#endif
<commit_msg>release thread handles when group is destructed (#1680)<commit_after>#ifndef BITCOIN_THREAD_GROUP_H
#define BITCOIN_THREAD_GROUP_H

#include <atomic>
#include <thread>
#include <vector>


extern std::atomic<bool> shutdown_threads;

class thread_group
{
private:
    std::vector<std::thread> threads;

public:
    void interrupt_all() { shutdown_threads.store(true); }
    template <class Fn, class... Args>
    void create_thread(Fn &&f, Args &&... args)
    {
        threads.push_back(std::thread(f, args...));
    }

    bool empty() { return threads.size() == 0; }
    void join_all()
    {
        for (size_t i = 0; i < threads.size(); i++)
        {
            if (threads[i].joinable())
            {
                threads[i].join();
            }
        }
        threads.clear();
    }

    // In the destructor, detach any threads that are still running.
    // We expect that you've cleaned them up if you want to, probably via join_all()
    ~thread_group()
    {
        for (auto &t : threads)
        {
            if (t.joinable())
                t.detach();
        }
    }
};

#endif

{'fraction_non_alphanumeric': 0.14118273841236015, 'fraction_numerical': 0.004262120404901438, 'mean_word_length': 2.243523316062176, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, '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': '3467054', 'n_tokens_mistral': 616, 'n_tokens_neox': 595, 'n_words': 145}