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; });
    }
};
相关推荐
geovindu19 分钟前
go: Iterative Algorithms
开发语言·后端·算法·golang·迭代算法
稚南城才子,乌衣巷风流2 小时前
块状链表:数据结构详解与实现
数据结构·链表
Zachery Pole2 小时前
CCF-CSP备战NO.7【队列】
算法
闪电悠米3 小时前
力扣hot100-48.旋转图像-转置翻转详解
算法·leetcode·职场和发展
满天星83035773 小时前
【算法】最长递增子序列(三种解法)
算法
hold?fish:palm3 小时前
kv存储主从复制的设计与实现
c++·redis·后端
啦啦啦啦啦zzzz4 小时前
算法:贪心算法
c++·算法·leetcode·贪心算法
charlie1145141914 小时前
现代C++工程实践 WeakPtr 实战(三):WeakPtrFactory 与「最后成员」惯用法
开发语言·c++·开源项目·现代c++
日拱一卒——功不唐捐5 小时前
红黑树删除(C语言)
c语言·数据结构
清泓y5 小时前
RAG 技术
算法·ai