c++ 任务队列实现

2020-11-30  本文已影响0人  help_youself
#include <iostream>
#include <memory>
#include <functional>
#include <deque>
#include <utility>

namespace std
{
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
}

class QueuedTask {
 public:
  QueuedTask() {}
  virtual ~QueuedTask() {}
  virtual bool Run() = 0;
};
template <class Closure>
class ClosureTask : public QueuedTask {
 public:
  explicit ClosureTask(Closure&& closure)
      : closure_(std::forward<Closure>(closure)) {}
 ~ClosureTask(){ std::cout<<"task dtor"<<std::endl;}
 private:
  bool Run() override {
    closure_();
    return true;
  }

  typename std::remove_const<
      typename std::remove_reference<Closure>::type>::type closure_;
};
template <class Closure, class Cleanup>
class ClosureTaskWithCleanup : public ClosureTask<Closure> {
 public:
  ClosureTaskWithCleanup(Closure&& closure, Cleanup&& cleanup)
      : ClosureTask<Closure>(std::forward<Closure>(closure)),
        cleanup_(std::forward<Cleanup>(cleanup)) {}
  ~ClosureTaskWithCleanup() { cleanup_(); }

 private:
  typename std::remove_const<
      typename std::remove_reference<Cleanup>::type>::type cleanup_;
};

// Convenience function to construct closures that can be passed directly
// to methods that support std::unique_ptr<QueuedTask> but not template
// based parameters.
template <class Closure>
static std::unique_ptr<QueuedTask> NewClosure(Closure&& closure) {
  return std::make_unique<ClosureTask<Closure>>(std::forward<Closure>(closure));
}

template <class Closure, class Cleanup>
static std::unique_ptr<QueuedTask> NewClosure(Closure&& closure,
                                              Cleanup&& cleanup) {
  return std::make_unique<ClosureTaskWithCleanup<Closure, Cleanup>>(
      std::forward<Closure>(closure), std::forward<Cleanup>(cleanup));
}






class Channel{
public:
    Channel(int a):a_(a){}
    ~Channel(){
        std::cout<<"channel dtor "<<a_<<std::endl;
    }
    int a_=0;
};
class Thread{
public:
template <class Closure,
          typename std::enable_if<!std::is_convertible<
              Closure,
              std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
void PostTask(Closure&& closure) {
  PostTask(NewClosure(std::forward<Closure>(closure)));
}

void PostTask(std::unique_ptr<QueuedTask> task){
    tasks_.push_back(std::move(task));
}
    void Run(){
        std::deque<std::unique_ptr<QueuedTask>> tasks;
        tasks.swap(tasks_);
        while(!tasks.empty()){
            tasks.front()->Run();
            tasks.pop_front();
        }
    }
    void AsynChannel(std::function<void(Channel*)> f){
        PostTask([this,f](){
                    std::cout<<"run task"<<std::endl;
                    auto channel=AllocateChannel();
                    f(channel);
                 });
    }
    Channel *AllocateChannel(){
        Channel *channel=new Channel(count_);
        count_++;
        return channel;
    }
private:
    std::deque<std::unique_ptr<QueuedTask>> tasks_;
    int count_=1;
};
class Request{
public:
    Request(Thread*thread):thread_(thread){}
    void Trigger(){
        thread_->AsynChannel([&](Channel*channel){
                                this->OnChannel(channel);
                                   });
    }
    void OnChannel(Channel*channel){
        std::cout<<"on channel: "<<channel->a_<<std::endl;
        channel_.reset(channel);

    }
    ~Request(){
        std::cout<<"Request dtor"<<std::endl;
    }
private:
    Thread *thread_=nullptr;
    std::unique_ptr<Channel> channel_;
};
int main(){
    std::unique_ptr<Thread> thread(new Thread());
    Request *request=new Request(thread.get());
    request->Trigger();
    request->Trigger();
    thread->PostTask([request]{
                        delete request;
                     });

    thread->Run();
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读