c++函数闭包实现多线程执行器

c++函数闭包实现多线程执行器

这里提供一个c++11实现函数闭包和多线程执行类的例子,主要包含如下特性:

  1. 一个简单的优先级任务队列
  2. 不使用c++14以上的语法,同时兼任较老的gcc的c++11编译器
  3. 实现了函数闭包
  4. variadic template
  5. 多线程示例

可作为学习c++模板的素材,因为实在简单,因而也没有比较解释了

/**
 * @brief Simple thread runner based on function closure and variadic parameters
 * packing.
 * @author zpfeng
 * @copyright (C) 2019-2020 zpfeng
 * @license BSD 3-CLAUSE
 */

#ifndef __SIMPLE_THREADING_H__
#define __SIMPLE_THREADING_H__

#include 
#include 
#include 
#include 
#include 
#include 
#include 

namespace simple_threading {

template  using Invoke = typename T::type;

template  struct IdxSeq { using type = IdxSeq; };

template  struct Concat;

template 
struct Concat, IdxSeq> : IdxSeq {};

template 
struct GenSeq : Invoke>, Invoke>>> {};

template <> struct GenSeq<0> : IdxSeq<> {};
template <> struct GenSeq<1> : IdxSeq<0> {};

template  using IdxSeqFor = GenSeq;

template 
constexpr void CallThreadFunc(Callable &&f, Tuple &&t, IdxSeq) {
    f(std::get(std::forward(t))...);
}

template 
constexpr void ApplyThreadFunc(Callable &&f, Tuple &&t) {
    CallThreadFunc(
        std::forward(f), std::forward(t),
        GenSeq::type>::value>());
}

template  struct Functor {
    Functor(Ret (*func)(Params...))
        : _func(func) {}
    Ret operator()(const Params &... param) const { return _func(param...); }
    Ret (*_func)(Params...);
};

template  struct ClassFunctor {
    ClassFunctor(Ret (Class::*func)(Params...), Class &obj)
        : _func(func)
        , _obj(obj) {}
    Ret operator()(const Params &... param) const { return (_obj.*_func)(param...); }
    Ret (Class::*_func)(Params...);
    Class &_obj;
};

template  struct ClassConstFunctor {
    ClassConstFunctor(Ret (Class::*func)(Params...) const, const Class &obj)
        : _func(func)
        , _obj(obj) {}
    Ret operator()(const Params &... param) const { return (_obj.*_func)(param...); }
    Ret (Class::*_func)(Params...) const;
    const Class &_obj;
};

template 
std::function ThreadFunc(Ret (*func)(Params...), Params2 &&... param) {
    auto f = Functor(func);
    return [f, tp = std::make_tuple(std::forward(param)...)] {
        ApplyThreadFunc(f, tp);
    };
}

template 
std::function ThreadFunc(Ret (Class::*func)(Params...), Class &obj,
                                 Params2 &&... param) {
    auto f = ClassFunctor(func, obj);
    return [f, tp = std::make_tuple(std::forward(param)...)] {
        ApplyThreadFunc(f, tp);
    };
}

template 
std::function ThreadFunc(Ret (Class::*func)(Params...) const, const Class &obj,
                                 Params2 &&... param) {
    auto f = ClassConstFunctor(func, obj);
    return [f, tp = std::make_tuple(std::forward(param)...)] {
        ApplyThreadFunc(f, tp);
    };
}

template 
std::shared_ptr MakeShared(Params &&... param) {
    return std::shared_ptr(new D(std::forward(param)...));
}

struct ThreadFunctorBase {
    ThreadFunctorBase(int priority)
        : _priority(priority) {}
    virtual ~ThreadFunctorBase() noexcept = default;
    virtual void operator()() const = 0;
    int _priority;
    struct LessThan {
        bool operator()(const std::shared_ptr &lhs,
                        const std::shared_ptr &rhs) const {
            return lhs->_priority < rhs->_priority;
        }
    };
};

template  struct ThreadFunctorImpl : ThreadFunctorBase {
    ThreadFunctorImpl(Callable f, int priority = 0)
        : ThreadFunctorBase(priority)
        , _f(std::move(f)) {}
    void operator()() const override { _f(); }
    Callable _f;
};

class SimpleTaskQueue {
  public:
    using task_type = std::shared_ptr;
    SimpleTaskQueue() = default;
    virtual ~SimpleTaskQueue() = default;
    void Push(task_type &&t) { _q.push(std::forward(t)); }
    bool Pop(task_type &t) {
        std::lock_guard lg(_lock);
        if (_q.empty())
            return false;
        else {
            t = _q.top();
            _q.pop();
            return true;
        }
    }

  private:
    std::mutex _lock;
    std::priority_queue, ThreadFunctorBase::LessThan>
        _q;
};

class SimpleThreadRunner {
  public:
    SimpleThreadRunner(int run_thread)
        : _thread_cnt(run_thread) {}
    ~SimpleThreadRunner() = default;
    template  void AddTask(Callable &&f, int priority = 0) {
        _q.Push(MakeShared>(f, priority));
    }
    void Start() {
        for (int i = 0; i < _thread_cnt; ++i) {
            std::thread t([this]() {
                SimpleTaskQueue::task_type f_ptr = nullptr;
                while (this->_q.Pop(f_ptr)) {
                    (*f_ptr)();
                }
            });
            _t.push_back(std::move(t));
        }
    }
    void Join() {
        for (auto &t : _t) {
            t.join();
        }
        _t.clear();
    }

  private:
    int _thread_cnt = 0;
    SimpleTaskQueue _q;
    std::vector _t;
};

} // namespace simple_threading

#endif

示例:

#include "threading.h"
#include 
using namespace std;
using namespace simple_threading;

class ABC {
  public:
    void heavy_method(size_t times, int job_id) {
        // cout << times << endl;
        size_t val = 0;
        for (size_t i = 0; i < times; ++i) {
            val += i * i * i;
        }
        cout << std::this_thread::get_id() << ": finish jobs" << job_id << " and val is:" << val << endl;
    }
};

size_t test_method(size_t times, int job_id) {
    size_t val = 0;
    for (size_t i = 0; i < times; ++i) {
        val += i * i * i;
    }
    cout << std::this_thread::get_id() << ": finish jobs" << job_id << " and val is:" << val << endl;
    return val;
}

int main() {
    SimpleThreadRunner sr(2);
    ABC abc;
    sr.AddTask(ThreadFunc(&test_method, 101233532, 9), 1);
    sr.AddTask(ThreadFunc(&test_method, 101232212, 10), 1);
    sr.AddTask(ThreadFunc(&test_method, 101235512, 11), 1);
    sr.AddTask(ThreadFunc(&test_method, 101236612, 12), 1);
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 100000000, 1));
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 104000000, 2), 10);
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 110000000, 3), 8);
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 100300000, 4));
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 100000010, 5));
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 101000000, 6), 10);
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 110000000, 7), 8);
    sr.AddTask(ThreadFunc(&ABC::heavy_method, abc, 100100000, 8));
    sr.Start();
    sr.Join();
    cout << "end" << endl;
    return 0;
}

你可能感兴趣的:(c++,c++)