blob: 88b824835218e672ce0e6a03c8b7f7c9a8f23d75 [file] [log] [blame]
/*
* 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_