#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;
}
网友评论