nnpp处理,线程

一个等待外部notify他的线程池

cpp 复制代码
class thread_pool_PDAC
{
  private:
    enum class worker_state
    {
        Idle,
        TryFetch,
        Work
    };

    enum class cu_state
    {
        Pending,
        Ready,
        Running
    };

    static const int MaxThreads = 16;

    std::atomic_bool _is_running;
    std::mutex _mutex;
    std::condition_variable _cond;
    std::condition_variable _finishedCond;
    size_t _thread_no;
    std::vector<std::thread> _threads;

    std::function<void(int, int)> _workTask;
    std::function<bool(int)> _checkTask;

    bool _needCheck = false;
    std::deque<int> _pendingCUs;
    std::queue<int> _readyCUs;
    std::unordered_map<int, cu_state> _cuStates;
    std::atomic<int> activeNum{0};

  public:
    thread_pool_PDAC(const thread_pool_PDAC &tp) = delete;
    thread_pool_PDAC &operator=(const thread_pool_PDAC &tp) = delete;

  public:
    thread_pool_PDAC(size_t no = 1) : _is_running(false), _thread_no(no)
    {
        if (_thread_no >= MaxThreads)
        {
            _thread_no = MaxThreads;
        }
        _workTask = [](int, int) {};
        _checkTask = [](int) { return true; };
    }

    ~thread_pool_PDAC()
    {
        if (_is_running)
        {
            stop();
        }
    }

  private:
    bool tryTakeReadyTaskLocked(int &cuIndex)
    {
        while (!_readyCUs.empty())
        {
            int candidate = _readyCUs.front();
            _readyCUs.pop();

            auto iter = _cuStates.find(candidate);
            if (iter == _cuStates.end() || iter->second != cu_state::Ready)
            {
                continue;
            }

            iter->second = cu_state::Running;
            cuIndex = candidate;

            if (!_readyCUs.empty())
            {
                _cond.notify_one();
            }
            return true;
        }

        return false;
    }

    bool tryTakePendingCandidateLocked(int &cuIndex)
    {
        while (!_pendingCUs.empty())
        {
            int candidate = _pendingCUs.front();
            _pendingCUs.pop_front();

            auto iter = _cuStates.find(candidate);
            if (iter == _cuStates.end() || iter->second != cu_state::Pending)
            {
                continue;
            }

            cuIndex = candidate;
            return true;
        }

        _needCheck = false;
        return false;
    }

    bool tryFetchReadyTask(int &cuIndex)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        return tryTakeReadyTaskLocked(cuIndex);
    }

    bool tryTakePendingCandidate(int &cuIndex)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        return tryTakePendingCandidateLocked(cuIndex);
    }

    bool promoteCheckedCandidate(int cuIndex)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        auto iter = _cuStates.find(cuIndex);
        if (iter == _cuStates.end())
        {
            return false;
        }

        if (iter->second != cu_state::Pending)
        {
            return false;
        }

        iter->second = cu_state::Running;
        return true;
    }

    void restorePendingCandidate(int cuIndex)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        auto iter = _cuStates.find(cuIndex);
        if (iter == _cuStates.end() || iter->second != cu_state::Pending)
        {
            return;
        }

        _pendingCUs.push_back(cuIndex);
        _needCheck = false;
    }

    void finishTask(int cuIndex)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        auto iter = _cuStates.find(cuIndex);
        if (iter != _cuStates.end() && iter->second == cu_state::Running)
        {
            _cuStates.erase(iter);
        }

        _finishedCond.notify_all();
        if (!_readyCUs.empty())
        {
            _cond.notify_one();
        }
    }

    void work(int threadIndex)
    {
        worker_state state = worker_state::Idle;
        int cuIndex = -1;

        while (_is_running)
        {
            switch (state)
            {
            case worker_state::Idle: {
                std::unique_lock<std::mutex> lock(_mutex);
                _cond.wait(lock, [this]() { return !_is_running || !_readyCUs.empty() || _needCheck; });
                if (!_is_running)
                {
                    return;
                }
                state = worker_state::TryFetch;
                break;
            }
            case worker_state::TryFetch: {
                if (tryFetchReadyTask(cuIndex))
                {
                    state = worker_state::Work;
                    break;
                }

                if (!tryTakePendingCandidate(cuIndex))
                {
                    state = worker_state::Idle;
                    break;
                }

                bool isReady = _checkTask ? _checkTask(cuIndex) : false;
                if (isReady && promoteCheckedCandidate(cuIndex))
                {
                    state = worker_state::Work;
                    break;
                }

                restorePendingCandidate(cuIndex);
                cuIndex = -1;
                state = worker_state::Idle;
                break;
            }
            case worker_state::Work: {
                ++activeNum;
                _workTask(threadIndex, cuIndex);
                --activeNum;
                finishTask(cuIndex);
                cuIndex = -1;
                state = worker_state::TryFetch;
                break;
            }
            }
        }
    }

  public:
    void setThreadNumber(size_t no)
    {
        if (no >= MaxThreads)
        {
            no = MaxThreads;
        }
        this->_thread_no = no;
    }

    void start()
    {
        this->_is_running = true;
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _needCheck = !_pendingCUs.empty();
        }

        for (size_t i = 0; i < _thread_no; i++)
        {
            _threads.emplace_back(std::thread(&thread_pool_PDAC::work, this, static_cast<int>(i)));
        }

        _cond.notify_all();
    }

    void stop()
    {
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _is_running = false;
            _needCheck = false;
        }
        _cond.notify_all();

        for (std::thread &thd : _threads)
        {
            if (thd.joinable())
            {
                thd.join();
            }
        }
        _threads.clear();
    }

    void setWorkTask(const std::function<void(int, int)> &t) { this->_workTask = t; }

    void setFetchTask(const std::function<bool(int)> &t) { this->_checkTask = t; }

    void EnqueueTask(int cuIndex)
    {
        if (!_is_running)
        {
            return;
        }

        std::lock_guard<std::mutex> lock(_mutex);
        auto inserted = _cuStates.emplace(cuIndex, cu_state::Pending);
        if (!inserted.second)
        {
            return;
        }

        _pendingCUs.push_back(cuIndex);
        _needCheck = true;
        _cond.notify_one();
        _finishedCond.notify_all();
    }

    void notify(int cuIndex)
    {
        if (!_is_running)
        {
            return;
        }

        std::lock_guard<std::mutex> lock(_mutex);
        auto iter = _cuStates.find(cuIndex);
        if (iter == _cuStates.end())
        {
            // 外界 CU,错误
            std::cerr << "[Error]: unregistered CU: " << cuIndex << std::endl;  
            return;
        }

        if (iter->second == cu_state::Pending)
        {
            iter->second = cu_state::Ready;
            _readyCUs.push(cuIndex);
            _cond.notify_one();
        }
    }

    void waitFinished()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _finishedCond.wait(lock, [this]() { return _cuStates.empty() && activeNum.load(std::memory_order_acquire) == 0; });
    }
};
相关推荐
QiLinkOS14 小时前
第三视觉理解徐玉生与他的商业活动(30)
大数据·c++·人工智能·算法·开源协议
mit6.82414 小时前
阅读的核心,是再读
c++
疯狂打码的少年14 小时前
【操作系统】页面置换算法(OPT/FIFO/LRU)
算法
小O的算法实验室14 小时前
2026年CIE,优化客货协同运输:综合地铁系统的列车容量动态分配
算法
Coder_Shenshen15 小时前
西门子S7CommPlus协议鉴权算法原理与流程详解
网络·后端·算法
硕风和炜16 小时前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集
upgrador16 小时前
基础知识:C++ STL构造函数的左闭右开惯例及其实现原理
开发语言·c++
我是一颗柠檬17 小时前
【Java项目技术亮点】加权轮询负载均衡算法
java·算法·负载均衡
灯厂码农17 小时前
C语言动态内存分配完全指南(malloc、calloc、realloc、free)
java·c语言·算法
凯瑟琳.奥古斯特18 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展