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; });
    }
};
相关推荐
是苏浙2 分钟前
Java实现链表2
java·开发语言·数据结构
郝学胜_神的一滴10 分钟前
CMake 018:解决头文件编译失效\&VS项目无法展示头文件难题
c++·cmake
KobeSacre11 分钟前
ThreadLocal 源码
数据结构
影视飓风TIM13 分钟前
C++ 核心语法进阶:【类和对象终章】从对象拷贝到友元与优化(补上期重载)
c++
小鹏linux13 分钟前
鸿蒙PC迁移:Tesseract OCR C++ 三方库鸿蒙适配全记录
c++·ocr·harmonyos
森G13 分钟前
65、UDP协议(拓展选学)---------网络编程
网络·c++·qt·网络协议·tcp/ip·udp
WWW652617 分钟前
代码随想录 打卡第五十八天
开发语言·c++·算法
pen-ai19 分钟前
【HistGBM 系列①】从决策树到梯度提升 —— GBDT 原理精讲
算法·决策树·机器学习
少司府23 分钟前
C++基础入门:_stack_queue 底层奥秘
开发语言·数据结构·c++·栈和队列·queue·stack
Black蜡笔小新28 分钟前
零代码私有化自动化AI算法训练服务器DLTM如何破解企业AI落地难题
人工智能·算法·自动化