| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Author: jmarantz@google.com (Joshua Marantz) |
| |
| #ifndef PAGESPEED_KERNEL_BASE_FUNCTION_H_ |
| #define PAGESPEED_KERNEL_BASE_FUNCTION_H_ |
| |
| #include "pagespeed/kernel/base/atomic_bool.h" |
| #include "pagespeed/kernel/base/basictypes.h" |
| |
| namespace net_instaweb { |
| |
| // Encapsulates a task to be run in response to some event, such as |
| // a Timer callback, an fetch, or a cache lookup. |
| // |
| // Users of interfaces requiring a Function* can either derive a new |
| // class from Function, or use one of the helper template-classes or |
| // MakeFunction variants below, which create delayed calls to class |
| // methods. |
| // |
| // Note that Functions by default are self-deleting after call, but |
| // you can override that with set_delete_after_callback(false). |
| // |
| // A Function will always have its Run method or its Cancel method |
| // called, never both. A Function should never be deleted without its |
| // Run/Cancel method being called (except if |
| // set_delete_after_callback(false)). |
| // |
| // Note that classes calling Functions use the CallRun or CallCancel methods, |
| // rather than calling Run or Cancel directly. This allows the Function class |
| // to enforce policy on making run & cancel mutually exclusive and implement |
| // delete-after-run. |
| class Function { |
| public: |
| Function(); |
| virtual ~Function(); |
| |
| // Functions used as Worker tasks can help the system shut down cleanly |
| // by calling quit_requested() periodically. To support this, Worker |
| // calls set_quit_requested_pointer so the Function object can access |
| // the atomic bool. |
| // |
| // Note that a strategy of allocating the AtomicBool inside the Function |
| // object exposes a shutdown race when the function completes and deletes |
| // itself. |
| void set_quit_requested_pointer(AtomicBool* x) { quit_requested_ = x; } |
| |
| // Allows an infrastructure (e.g. Worker or Alarm) to request that |
| // a running Function stop soon, as it is being shut down. |
| // |
| // This can should only be called during the Run() method. |
| bool quit_requested() const { |
| return (quit_requested_ != NULL) && quit_requested_->value(); |
| } |
| |
| // Implementors of Function interfaces should call via these helper methods |
| // to initiate Run and Cancel callbacks. This helps centralize deletion of |
| // callbacks after they are called. |
| void CallRun(); |
| void CallCancel(); |
| |
| // By default, Functions delete themselves after being called. Call |
| // this method to override. If the Function is going to be re-called, |
| // Reset() must be called on it first. Will not take effect if called |
| // within Run() or Cancel(). |
| void set_delete_after_callback(bool x) { delete_after_callback_ = x; } |
| |
| // Clears the state of the function so that it can be called or cancelled |
| // again. This only makes sense to call if set_delete_after_callback(false) |
| // has been called. |
| void Reset(); |
| |
| protected: |
| // Callers must override this to define the action to take when a closure |
| // is run. If this is called, Cancel() should not be called. This is |
| // a convention that's expected of callers of Function objects, but is |
| // not enforced by the Function implementation. |
| virtual void Run() = 0; |
| |
| // Informs a the Function that it is being shut down. If this is |
| // called, Run() should not be called. This should never be called |
| // while a function is running. See also set_quit_requested(), |
| // which can be called during Run(), so that Run() implementations |
| // can check quit_requested() at their convenience to stop the |
| // operation in progress. |
| virtual void Cancel() {} |
| |
| private: |
| AtomicBool* quit_requested_; |
| bool run_called_; |
| bool cancel_called_; |
| bool delete_after_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Function); |
| }; |
| |
| // A Macro is recommended for making a readable call to a pointer-to-member |
| // function per section 33.6 of |
| // http://www.parashift.com/c++-faq-lite/pointers-to-members.html |
| #define CALL_MEMBER_FN(object, ptrToMember) ((this->object)->*(ptrToMember)) |
| |
| // Base class for a MemberFunctionN classes, implementing an optional Cancel |
| // via a Member function. |
| template<class C> |
| class MemberFunctionBase : public Function { |
| public: |
| explicit MemberFunctionBase(C* c) : object_(c) {} |
| |
| protected: |
| C* object_; |
| }; |
| |
| // Captures a delayed call to a 0-arg member function as a closure. |
| template<class C> |
| class MemberFunction0 : public MemberFunctionBase<C> { |
| public: |
| typedef void (C::*Func)(); |
| |
| // Constructor supplying a Run method, but no Cancel method. |
| MemberFunction0(Func f, C* c) : MemberFunctionBase<C>(c), run_(f), |
| cancel_(NULL) { |
| } |
| |
| // Constructor supplying a Run method and a Cancel method. |
| MemberFunction0(Func f, Func cancel, C* c) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(cancel) {} |
| |
| protected: |
| virtual void Run() { CALL_MEMBER_FN(object_, run_)(); } |
| virtual void Cancel() { |
| if (cancel_ != NULL) { |
| CALL_MEMBER_FN(object_, cancel_)(); |
| } |
| } |
| |
| private: |
| Func run_; |
| Func cancel_; |
| }; |
| |
| // Captures a delayed call to a 1-arg member function as a closure. |
| template<class C, typename T1> |
| class MemberFunction1 : public MemberFunctionBase<C> { |
| public: |
| typedef void (C::*Func)(T1); |
| |
| // Constructor supplying a Run method, but no Cancel method. |
| MemberFunction1(Func f, C* c, T1 v1) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(NULL), v1_(v1) {} |
| |
| // Constructor supplying a Run method and a Cancel method. |
| MemberFunction1(Func f, Func cancel, |
| C* c, T1 v1) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(cancel), v1_(v1) {} |
| |
| protected: |
| virtual void Run() { CALL_MEMBER_FN(object_, run_)(v1_); } |
| virtual void Cancel() { |
| if (cancel_ != NULL) { |
| CALL_MEMBER_FN(object_, cancel_)(v1_); |
| } |
| } |
| |
| private: |
| Func run_; |
| Func cancel_; |
| T1 v1_; |
| }; |
| |
| // Captures a delayed call to a 2-arg member function as a closure. |
| template<class C, typename T1, typename T2> |
| class MemberFunction2 : public MemberFunctionBase<C> { |
| public: |
| typedef void (C::*Func)(T1, T2); |
| |
| // Constructor supplying a Run method, but no Cancel method. |
| MemberFunction2(Func f, C* c, T1 v1, T2 v2) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(NULL), v1_(v1), v2_(v2) {} |
| |
| // Constructor supplying a Run method and a Cancel method. |
| MemberFunction2(Func f, Func cancel, |
| C* c, T1 v1, T2 v2) |
| : MemberFunctionBase<C>(c), |
| run_(f), cancel_(cancel), |
| v1_(v1), v2_(v2) {} |
| |
| protected: |
| virtual void Run() { CALL_MEMBER_FN(object_, run_)(v1_, v2_); } |
| virtual void Cancel() { |
| if (cancel_ != NULL) { |
| CALL_MEMBER_FN(object_, cancel_)(v1_, v2_); |
| } |
| } |
| |
| private: |
| Func run_; |
| Func cancel_; |
| T1 v1_; |
| T2 v2_; |
| }; |
| |
| // Captures a delayed call to a 3-arg member function as a closure. |
| template<class C, typename T1, typename T2, typename T3> |
| class MemberFunction3 : public MemberFunctionBase<C> { |
| public: |
| typedef void (C::*Func)(T1, T2, T3); |
| |
| // Constructor supplying a Run method, but no Cancel method. |
| MemberFunction3(Func f, C* c, T1 v1, T2 v2, T3 v3) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(NULL), v1_(v1), v2_(v2), |
| v3_(v3) { |
| } |
| |
| // Constructor supplying a Run method and a Cancel method. |
| MemberFunction3(Func f, Func cancel, |
| C* c, T1 v1, T2 v2, T3 v3) |
| : MemberFunctionBase<C>(c), |
| run_(f), cancel_(cancel), |
| v1_(v1), v2_(v2), v3_(v3) {} |
| |
| protected: |
| virtual void Run() { CALL_MEMBER_FN(object_, run_)(v1_, v2_, v3_); } |
| virtual void Cancel() { |
| if (cancel_ != NULL) { |
| CALL_MEMBER_FN(object_, cancel_)(v1_, v2_, v3_); |
| } |
| } |
| |
| private: |
| Func run_; |
| Func cancel_; |
| T1 v1_; |
| T2 v2_; |
| T3 v3_; |
| }; |
| |
| // Captures a delayed call to a 4-arg member function as a closure. |
| template<class C, typename T1, typename T2, typename T3, typename T4> |
| class MemberFunction4 : public MemberFunctionBase<C> { |
| public: |
| typedef void (C::*Func)(T1, T2, T3, T4); |
| |
| // Constructor supplying a Run method, but no Cancel method. |
| MemberFunction4(Func f, C* c, T1 v1, T2 v2, T3 v3, T4 v4) |
| : MemberFunctionBase<C>(c), run_(f), cancel_(NULL), v1_(v1), v2_(v2), |
| v3_(v3), v4_(v4) { |
| } |
| |
| // Constructor supplying a Run method and a Cancel method. |
| MemberFunction4(Func f, Func cancel, |
| C* c, T1 v1, T2 v2, T3 v3, T4 v4) |
| : MemberFunctionBase<C>(c), |
| run_(f), cancel_(cancel), |
| v1_(v1), v2_(v2), v3_(v3), v4_(v4) {} |
| |
| protected: |
| virtual void Run() { CALL_MEMBER_FN(object_, run_)(v1_, v2_, v3_, v4_); } |
| virtual void Cancel() { |
| if (cancel_ != NULL) { |
| CALL_MEMBER_FN(object_, cancel_)(v1_, v2_, v3_, v4_); |
| } |
| } |
| |
| private: |
| Func run_; |
| Func cancel_; |
| T1 v1_; |
| T2 v2_; |
| T3 v3_; |
| T4 v4_; |
| }; |
| |
| #undef CALL_MEMBER_FN |
| |
| // Makes a Function* that calls a 0-arg class method. |
| template<class C> |
| Function* MakeFunction(C* object, void (C::*run)()) { |
| return new MemberFunction0<C>(run, object); |
| } |
| |
| // Makes a Function* that calls a 0-arg class method, or a 0-arg cancel |
| // method. |
| template<class C> |
| Function* MakeFunction(C* object, void (C::*run)(), void (C::*cancel)()) { |
| return new MemberFunction0<C>(run, cancel, object); |
| } |
| |
| // Makes a Function* that calls a 1-arg class method. |
| template<class C, class T> |
| Function* MakeFunction(C* object, void (C::*run)(T), T t) { |
| return new MemberFunction1<C, T>(run, object, t); |
| } |
| |
| // Makes a Function* that calls a 1-arg class method, or a 1-arg cancel |
| // method. |
| template<class C, class T> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T), |
| void (C::*cancel)(T), T t) { |
| return new MemberFunction1<C, T>(run, cancel, object, t); |
| } |
| |
| // Makes a Function* that calls a 2-arg class method. |
| template<class C, class T, class U> |
| Function* MakeFunction(C* object, void (C::*run)(T, U), T t, U u) { |
| return new MemberFunction2<C, T, U>(run, object, t, u); |
| } |
| |
| // Makes a Function* that calls a 2-arg class method, or a 2-arg cancel |
| // method. |
| template<class C, class T, class U> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T, U), |
| void (C::*cancel)(T, U), |
| T t, U u) { |
| return new MemberFunction2<C, T, U>(run, cancel, object, t, u); |
| } |
| |
| // Makes a Function* that calls a 3-arg class method. |
| template<class C, class T, class U, class V> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T, U, V), |
| T t, U u, V v) { |
| return new MemberFunction3<C, T, U, V>(run, object, t, u, v); |
| } |
| |
| // Makes a Function* that calls a 3-arg class method, or a 3-arg cancel |
| // method. |
| template<class C, class T, class U, class V> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T, U, V), |
| void (C::*cancel)(T, U, V), |
| T t, U u, V v) { |
| return new MemberFunction3<C, T, U, V>(run, cancel, object, t, u, v); |
| } |
| |
| // Makes a Function* that calls a 4-arg class method. |
| template<class C, class T, class U, class V, class W> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T, U, V, W), |
| T t, U u, V v, W w) { |
| return new MemberFunction4<C, T, U, V, W>(run, object, t, u, v, w); |
| } |
| |
| // Makes a Function* that calls a 4-arg class method, or a 4-arg cancel |
| // method. |
| template<class C, class T, class U, class V, class W> |
| Function* MakeFunction(C* object, |
| void (C::*run)(T, U, V, W), |
| void (C::*cancel)(T, U, V, W), |
| T t, U u, V v, W w) { |
| return new MemberFunction4<C, T, U, V, W>(run, cancel, object, t, u, v, w); |
| } |
| |
| } // namespace net_instaweb |
| |
| #endif // PAGESPEED_KERNEL_BASE_FUNCTION_H_ |