Task

class Task : public tracked_objects::Tracked {

 public:

  Task() {}

  virtual ~Task() {}

 

  // Tasks are automatically deleted after Run is called.

  virtual void Run() = 0;

};

 

class CancelableTask : public Task {

 public:

  // Not all tasks support cancellation.

  virtual void Cancel() = 0;

};

 

// Scoped Factories ------------------------------------------------------------

//

// These scoped factory objects can be used by non-refcounted objects to safely

// place tasks in a message loop.  Each factory guarantees that the tasks it

// produces will not run after the factory is destroyed.  Commonly, factories

// are declared as class members, so the class' tasks will automatically cancel

// when the class instance is destroyed.

//

// Exampe Usage:

//

// class MyClass {

//  private:

//   // This factory will be used to schedule invocations of SomeMethod.

//   ScopedRunnableMethodFactory<MyClass> some_method_factory_;

//

//  public:

//   // It is safe to suppress warning 4355 here.

//   MyClass() : some_method_factory_(this) { }

//

//   void SomeMethod() {

//     // If this function might be called directly, you might want to revoke

//     // any outstanding runnable methods scheduled to call it.  If it's not

//     // referenced other than by the factory, this is unnecessary.

//     some_method_factory_.RevokeAll();

//     ...

//   }

//

//   void ScheduleSomeMethod() {

//     // If you'd like to only only have one pending task at a time, test for

//     // |empty| before manufacturing another task.

//     if (!some_method_factory_.empty())

//       return;

//

//     // The factories are not thread safe, so always invoke on

//     // |MessageLoop::current()|.

//     MessageLoop::current()->PostDelayedTask(FROM_HERE,

//         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),

//         kSomeMethodDelayMS);

//   }

// };

 

// A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from

// running after it is destroyed.

template<class TaskType>

class ScopedTaskFactory : public RevocableStore {

 public:

  ScopedTaskFactory() { }

 

  // Create a new task.

  inline TaskType* NewTask() {

    return new TaskWrapper(this);

  }

 

  class TaskWrapper : public TaskType, public NonThreadSafe {

   public:

    explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }

 

    virtual void Run() {

      if (!revocable_.revoked())

        TaskType::Run();

    }

 

   private:

    Revocable revocable_;

 

    DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);

  };

 

 private:

  DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory);

};

 

// A ScopedRunnableMethodFactory creates runnable methods for a specified

// object.  This is particularly useful for generating callbacks for

// non-reference counted objects when the factory is a member of the object.

template<class T>

class ScopedRunnableMethodFactory : public RevocableStore {

 public:

  explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }

 

  template <class Method>

  inline Task* NewRunnableMethod(Method method) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple0> >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple());

    return task;

  }

 

  template <class Method, class A>

  inline Task* NewRunnableMethod(Method method, const A& a) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple1<A> > >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple(a));

    return task;

  }

 

  template <class Method, class A, class B>

  inline Task* NewRunnableMethod(Method method, const A& a, const B& b) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple(a, b));

    return task;

  }

 

  template <class Method, class A, class B, class C>

  inline Task* NewRunnableMethod(Method method,

                                 const A& a,

                                 const B& b,

                                 const C& c) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple(a, b, c));

    return task;

  }

 

  template <class Method, class A, class B, class C, class D>

  inline Task* NewRunnableMethod(Method method,

                                 const A& a,

                                 const B& b,

                                 const C& c,

                                 const D& d) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple(a, b, c, d));

    return task;

  }

 

  template <class Method, class A, class B, class C, class D, class E>

  inline Task* NewRunnableMethod(Method method,

                                 const A& a,

                                 const B& b,

                                 const C& c,

                                 const D& d,

                                 const E& e) {

    typedef typename ScopedTaskFactory<RunnableMethod<

        Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper;

 

    TaskWrapper* task = new TaskWrapper(this);

    task->Init(object_, method, MakeTuple(a, b, c, d, e));

    return task;

  }

 

 protected:

  template <class Method, class Params>

  class RunnableMethod : public Task {

   public:

    RunnableMethod() { }

 

    void Init(T* obj, Method meth, const Params& params) {

      obj_ = obj;

      meth_ = meth;

      params_ = params;

    }

 

    virtual void Run() { DispatchToMethod(obj_, meth_, params_); }

 

   private:

    T* obj_;

    Method meth_;

    Params params_;

 

    DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);

  };

 

 private:

  T* object_;

 

  DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory);

};

 

// General task implementations ------------------------------------------------

 

// Task to delete an object

template<class T>

class DeleteTask : public CancelableTask {

 public:

  explicit DeleteTask(T* obj) : obj_(obj) {

  }

  virtual void Run() {

    delete obj_;

  }

  virtual void Cancel() {

    obj_ = NULL;

  }

 private:

  T* obj_;

};

 

// Task to Release() an object

template<class T>

class ReleaseTask : public CancelableTask {

 public:

  explicit ReleaseTask(T* obj) : obj_(obj) {

  }

  virtual void Run() {

    if (obj_)

      obj_->Release();

  }

  virtual void Cancel() {

    obj_ = NULL;

  }

 private:

  T* obj_;

};

 

// RunnableMethodTraits --------------------------------------------------------

//

// This traits-class is used by RunnableMethod to manage the lifetime of the

// callee object.  By default, it is assumed that the callee supports AddRef

// and Release methods.  A particular class can specialize this template to

// define other lifetime management.  For example, if the callee is known to

// live longer than the RunnableMethod object, then a RunnableMethodTraits

// struct could be defined with empty RetainCallee and ReleaseCallee methods.

 

template <class T>

struct RunnableMethodTraits {

  static void RetainCallee(T* obj) {

    obj->AddRef();

  }

  static void ReleaseCallee(T* obj) {

    obj->Release();

  }

};

 

// RunnableMethod and RunnableFunction -----------------------------------------

//

// Runnable methods are a type of task that call a function on an object when

// they are run. We implement both an object and a set of NewRunnableMethod and

// NewRunnableFunction functions for convenience. These functions are

// overloaded and will infer the template types, simplifying calling code.

//

// The template definitions all use the following names:

// T                - the class type of the object you're supplying

//                    this is not needed for the Static version of the call

// Method/Function  - the signature of a pointer to the method or function you

//                    want to call

// Param            - the parameter(s) to the method, possibly packed as a Tuple

// A                - the first parameter (if any) to the method

// B                - the second parameter (if any) to the mathod

//

// Put these all together and you get an object that can call a method whose

// signature is:

//   R T::MyFunction([A[, B]])

//

// Usage:

// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])

// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])

 

// RunnableMethod and NewRunnableMethod implementation -------------------------

 

template <class T, class Method, class Params>

class RunnableMethod : public CancelableTask,

                       public RunnableMethodTraits<T> {

 public:

  RunnableMethod(T* obj, Method meth, const Params& params)

      : obj_(obj), meth_(meth), params_(params) {

    RetainCallee(obj_);

  }

  ~RunnableMethod() {

    ReleaseCallee();

  }

 

  virtual void Run() {

    if (obj_)

      DispatchToMethod(obj_, meth_, params_);

  }

 

  virtual void Cancel() {

    ReleaseCallee();

  }

 

 private:

  void ReleaseCallee() {

    if (obj_) {

      RunnableMethodTraits<T>::ReleaseCallee(obj_);

      obj_ = NULL;

    }

  }

 

  T* obj_;

  Method meth_;

  Params params_;

};

 

template <class T, class Method>

inline CancelableTask* NewRunnableMethod(T* object, Method method) {

  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());

}

 

template <class T, class Method, class A>

inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {

  return new RunnableMethod<T, Method, Tuple1<A> >(object,

                                                   method,

                                                   MakeTuple(a));

}

 

template <class T, class Method, class A, class B>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

const A& a, const B& b) {

  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,

                                                      MakeTuple(a, b));

}

 

template <class T, class Method, class A, class B, class C>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

                                          const A& a, const B& b, const C& c) {

  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,

                                                         MakeTuple(a, b, c));

}

 

template <class T, class Method, class A, class B, class C, class D>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

                                          const A& a, const B& b,

                                          const C& c, const D& d) {

  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,

                                                            MakeTuple(a, b,

                                                                      c, d));

}

 

template <class T, class Method, class A, class B, class C, class D, class E>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

                                          const A& a, const B& b,

                                          const C& c, const D& d, const E& e) {

  return new RunnableMethod<T,

                            Method,

                            Tuple5<A, B, C, D, E> >(object,

                                                    method,

                                                    MakeTuple(a, b, c, d, e));

}

 

template <class T, class Method, class A, class B, class C, class D, class E,

          class F>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

                                          const A& a, const B& b,

                                          const C& c, const D& d, const E& e,

                                          const F& f) {

  return new RunnableMethod<T,

                            Method,

                            Tuple6<A, B, C, D, E, F> >(object,

                                                       method,

                                                       MakeTuple(a, b, c, d, e,

                                                                 f));

}

 

template <class T, class Method, class A, class B, class C, class D, class E,

          class F, class G>

inline CancelableTask* NewRunnableMethod(T* object, Method method,

                                         const A& a, const B& b,

                                         const C& c, const D& d, const E& e,

                                         const F& f, const G& g) {

  return new RunnableMethod<T,

                            Method,

                            Tuple7<A, B, C, D, E, F, G> >(object,

                                                          method,

                                                          MakeTuple(a, b, c, d,

                                                                    e, f, g));

}

 

// RunnableFunction and NewRunnableFunction implementation ---------------------

 

template <class Function, class Params>

class RunnableFunction : public CancelableTask {

 public:

  RunnableFunction(Function function, const Params& params)

      : function_(function), params_(params) {

  }

 

  ~RunnableFunction() {

  }

 

  virtual void Run() {

    if (function_)

      DispatchToFunction(function_, params_);

  }

 

  virtual void Cancel() {

  }

 

 private:

  Function function_;

  Params params_;

};

 

template <class Function>

inline CancelableTask* NewRunnableFunction(Function function) {

  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());

}

 

template <class Function, class A>

inline CancelableTask* NewRunnableFunction(Function function, const A& a) {

  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));

}

 

template <class Function, class A, class B>

inline CancelableTask* NewRunnableFunction(Function function,

                                           const A& a, const B& b) {

  return new RunnableFunction<Function, Tuple2<A, B> >(function,

                                                       MakeTuple(a, b));

}

 

template <class Function, class A, class B, class C>

inline CancelableTask* NewRunnableFunction(Function function,

                                           const A& a, const B& b,

                                           const C& c) {

  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,

                                                          MakeTuple(a, b, c));

}

 

template <class Function, class A, class B, class C, class D>

inline CancelableTask* NewRunnableFunction(Function function,

                                           const A& a, const B& b,

                                           const C& c, const D& d) {

  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,

                                                             MakeTuple(a, b,

                                                                       c, d));

}

 

template <class Function, class A, class B, class C, class D, class E>

inline CancelableTask* NewRunnableFunction(Function function,

                                           const A& a, const B& b,

                                           const C& c, const D& d,

                                           const E& e) {

  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,

                                                                MakeTuple(a, b,

                                                                          c, d,

                                                                          e));

}

 

// Callback --------------------------------------------------------------------

//

// A Callback is like a Task but with unbound parameters. It is basically an

// object-oriented function pointer.

//

// Callbacks are designed to work with Tuples.  A set of helper functions and

// classes is provided to hide the Tuple details from the consumer.  Client

// code will generally work with the CallbackRunner base class, which merely

// provides a Run method and is returned by the New* functions. This allows

// users to not care which type of class implements the callback, only that it

// has a certain number and type of arguments.

//

// The implementation of this is done by CallbackImpl, which inherits

// CallbackStorage to store the data. This allows the storage of the data

// (requiring the class type T) to be hidden from users, who will want to call

// this regardless of the implementor's type T.

//

// Note that callbacks currently have no facility for cancelling or abandoning

// them. We currently handle this at a higher level for cases where this is

// necessary. The pointer in a callback must remain valid until the callback

// is made.

//

// Like Task, the callback executor is responsible for deleting the callback

// pointer once the callback has executed.

//

// Example client usage:

//   void Object::DoStuff(int, string);

//   Callback2<int, string>::Type* callback =

//       NewCallback(obj, &Object::DoStuff);

//   callback->Run(5, string("hello"));

//   delete callback;

// or, equivalently, using tuples directly:

//   CallbackRunner<Tuple2<int, string> >* callback =

//       NewCallback(obj, &Object::DoStuff);

//   callback->RunWithParams(MakeTuple(5, string("hello")));

 

// Base for all Callbacks that handles storage of the pointers.

template <class T, typename Method>

class CallbackStorage {

 public:

  CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {

  }

 

 protected:

  T* obj_;

  Method meth_;

};

 

// Interface that is exposed to the consumer, that does the actual calling

// of the method.

template <typename Params>

class CallbackRunner {

 public:

  typedef Params TupleType;

 

  virtual ~CallbackRunner() {}

  virtual void RunWithParams(const Params& params) = 0;

 

  // Convenience functions so callers don't have to deal with Tuples.

  inline void Run() {

    RunWithParams(Tuple0());

  }

 

  template <typename Arg1>

  inline void Run(const Arg1& a) {

    RunWithParams(Params(a));

  }

 

  template <typename Arg1, typename Arg2>

  inline void Run(const Arg1& a, const Arg2& b) {

    RunWithParams(Params(a, b));

  }

 

  template <typename Arg1, typename Arg2, typename Arg3>

  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {

    RunWithParams(Params(a, b, c));

  }

 

  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>

  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {

    RunWithParams(Params(a, b, c, d));

  }

 

  template <typename Arg1, typename Arg2, typename Arg3,

            typename Arg4, typename Arg5>

  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,

                  const Arg4& d, const Arg5& e) {

    RunWithParams(Params(a, b, c, d, e));

  }

};

 

template <class T, typename Method, typename Params>

class CallbackImpl : public CallbackStorage<T, Method>,

                     public CallbackRunner<Params> {

 public:

  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {

  }

  virtual void RunWithParams(const Params& params) {

    // use "this->" to force C++ to look inside our templatized base class; see

    // Effective C++, 3rd Ed, item 43, p210 for details.

    DispatchToMethod(this->obj_, this->meth_, params);

  }

};

 

// 0-arg implementation

struct Callback0 {

  typedef CallbackRunner<Tuple0> Type;

};

 

template <class T>

typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {

  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);

}

 

// 1-arg implementation

template <typename Arg1>

struct Callback1 {

  typedef CallbackRunner<Tuple1<Arg1> > Type;

};

 

template <class T, typename Arg1>

typename Callback1<Arg1>::Type* NewCallback(T* object,

                                            void (T::*method)(Arg1)) {

  return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);

}

 

// 2-arg implementation

template <typename Arg1, typename Arg2>

struct Callback2 {

  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;

};

 

template <class T, typename Arg1, typename Arg2>

typename Callback2<Arg1, Arg2>::Type* NewCallback(

    T* object,

    void (T::*method)(Arg1, Arg2)) {

  return new CallbackImpl<T, void (T::*)(Arg1, Arg2),

      Tuple2<Arg1, Arg2> >(object, method);

}

 

// 3-arg implementation

template <typename Arg1, typename Arg2, typename Arg3>

struct Callback3 {

  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;

};

 

template <class T, typename Arg1, typename Arg2, typename Arg3>

typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(

    T* object,

    void (T::*method)(Arg1, Arg2, Arg3)) {

  return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),

      Tuple3<Arg1, Arg2, Arg3> >(object, method);

}

 

// 4-arg implementation

template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>

struct Callback4 {

  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;

};

 

template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>

typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(

    T* object,

    void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {

  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),

      Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);

}

 

// 5-arg implementation

template <typename Arg1, typename Arg2, typename Arg3,

          typename Arg4, typename Arg5>

struct Callback5 {

  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;

};

 

template <class T, typename Arg1, typename Arg2,

          typename Arg3, typename Arg4, typename Arg5>

typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(

    T* object,

    void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {

  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),

      Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);

}

 

// An UnboundMethod is a wrapper for a method where the actual object is

// provided at Run dispatch time.

template <class T, class Method, class Params>

class UnboundMethod {

 public:

  UnboundMethod(Method m, Params p) : m_(m), p_(p) {}

  void Run(T* obj) const {

    DispatchToMethod(obj, m_, p_);

  }

 private:

  Method m_;

  Params p_;

};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值