blob: 6888f136dd00011349641ea70972939a4ee121dd [file] [log] [blame]
#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
#include <type_traits>
#include <google/protobuf/stubs/macros.h>
// ===================================================================
// emulates google3/base/callback.h
namespace google {
namespace protobuf {
// Abstract interface for a callback. When calling an RPC, you must provide
// a Closure to call when the procedure completes. See the Service interface
// in service.h.
//
// To automatically construct a Closure which calls a particular function or
// method with a particular set of parameters, use the NewCallback() function.
// Example:
// void FooDone(const FooResponse* response) {
// ...
// }
//
// void CallFoo() {
// ...
// // When done, call FooDone() and pass it a pointer to the response.
// Closure* callback = NewCallback(&FooDone, response);
// // Make the call.
// service->Foo(controller, request, response, callback);
// }
//
// Example that calls a method:
// class Handler {
// public:
// ...
//
// void FooDone(const FooResponse* response) {
// ...
// }
//
// void CallFoo() {
// ...
// // When done, call FooDone() and pass it a pointer to the response.
// Closure* callback = NewCallback(this, &Handler::FooDone, response);
// // Make the call.
// service->Foo(controller, request, response, callback);
// }
// };
//
// Currently NewCallback() supports binding zero, one, or two arguments.
//
// Callbacks created with NewCallback() automatically delete themselves when
// executed. They should be used when a callback is to be called exactly
// once (usually the case with RPC callbacks). If a callback may be called
// a different number of times (including zero), create it with
// NewPermanentCallback() instead. You are then responsible for deleting the
// callback (using the "delete" keyword as normal).
//
// Note that NewCallback() is a bit touchy regarding argument types. Generally,
// the values you provide for the parameter bindings must exactly match the
// types accepted by the callback function. For example:
// void Foo(string s);
// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string
// NewCallback(&Foo, string("foo")); // WORKS
// Also note that the arguments cannot be references:
// void Foo(const string& s);
// string my_str;
// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes.
// However, correctly-typed pointers will work just fine.
class LIBPROTOBUF_EXPORT Closure {
public:
Closure() {}
virtual ~Closure();
virtual void Run() = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
};
template<typename R>
class ResultCallback {
public:
ResultCallback() {}
virtual ~ResultCallback() {}
virtual R Run() = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
};
template<typename R, typename A1>
class LIBPROTOBUF_EXPORT ResultCallback1 {
public:
ResultCallback1() {}
virtual ~ResultCallback1() {}
virtual R Run(A1) = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
};
template<typename R, typename A1, typename A2>
class LIBPROTOBUF_EXPORT ResultCallback2 {
public:
ResultCallback2() {}
virtual ~ResultCallback2() {}
virtual R Run(A1,A2) = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
};
namespace internal {
class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
public:
typedef void (*FunctionType)();
FunctionClosure0(FunctionType function, bool self_deleting)
: function_(function), self_deleting_(self_deleting) {}
~FunctionClosure0();
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
function_();
if (needs_delete) delete this;
}
private:
FunctionType function_;
bool self_deleting_;
};
template <typename Class>
class MethodClosure0 : public Closure {
public:
typedef void (Class::*MethodType)();
MethodClosure0(Class* object, MethodType method, bool self_deleting)
: object_(object), method_(method), self_deleting_(self_deleting) {}
~MethodClosure0() {}
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
(object_->*method_)();
if (needs_delete) delete this;
}
private:
Class* object_;
MethodType method_;
bool self_deleting_;
};
template <typename Arg1>
class FunctionClosure1 : public Closure {
public:
typedef void (*FunctionType)(Arg1 arg1);
FunctionClosure1(FunctionType function, bool self_deleting,
Arg1 arg1)
: function_(function), self_deleting_(self_deleting),
arg1_(arg1) {}
~FunctionClosure1() {}
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
function_(arg1_);
if (needs_delete) delete this;
}
private:
FunctionType function_;
bool self_deleting_;
Arg1 arg1_;
};
template <typename Class, typename Arg1>
class MethodClosure1 : public Closure {
public:
typedef void (Class::*MethodType)(Arg1 arg1);
MethodClosure1(Class* object, MethodType method, bool self_deleting,
Arg1 arg1)
: object_(object), method_(method), self_deleting_(self_deleting),
arg1_(arg1) {}
~MethodClosure1() {}
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
(object_->*method_)(arg1_);
if (needs_delete) delete this;
}
private:
Class* object_;
MethodType method_;
bool self_deleting_;
Arg1 arg1_;
};
template <typename Arg1, typename Arg2>
class FunctionClosure2 : public Closure {
public:
typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2);
FunctionClosure2(FunctionType function, bool self_deleting,
Arg1 arg1, Arg2 arg2)
: function_(function), self_deleting_(self_deleting),
arg1_(arg1), arg2_(arg2) {}
~FunctionClosure2() {}
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
function_(arg1_, arg2_);
if (needs_delete) delete this;
}
private:
FunctionType function_;
bool self_deleting_;
Arg1 arg1_;
Arg2 arg2_;
};
template <typename Class, typename Arg1, typename Arg2>
class MethodClosure2 : public Closure {
public:
typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2);
MethodClosure2(Class* object, MethodType method, bool self_deleting,
Arg1 arg1, Arg2 arg2)
: object_(object), method_(method), self_deleting_(self_deleting),
arg1_(arg1), arg2_(arg2) {}
~MethodClosure2() {}
void Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
(object_->*method_)(arg1_, arg2_);
if (needs_delete) delete this;
}
private:
Class* object_;
MethodType method_;
bool self_deleting_;
Arg1 arg1_;
Arg2 arg2_;
};
template<typename R>
class FunctionResultCallback_0_0 : public ResultCallback<R> {
public:
typedef R (*FunctionType)();
FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
: function_(function), self_deleting_(self_deleting) {}
~FunctionResultCallback_0_0() {}
R Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
R result = function_();
if (needs_delete) delete this;
return result;
}
private:
FunctionType function_;
bool self_deleting_;
};
template<typename R, typename P1>
class FunctionResultCallback_1_0 : public ResultCallback<R> {
public:
typedef R (*FunctionType)(P1);
FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
P1 p1)
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
~FunctionResultCallback_1_0() {}
R Run() {
bool needs_delete = self_deleting_; // read in case callback deletes
R result = function_(p1_);
if (needs_delete) delete this;
return result;
}
private:
FunctionType function_;
bool self_deleting_;
P1 p1_;
};
template<typename R, typename Arg1>
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
public:
typedef R (*FunctionType)(Arg1 arg1);
FunctionResultCallback_0_1(FunctionType function, bool self_deleting)
: function_(function), self_deleting_(self_deleting) {}
~FunctionResultCallback_0_1() {}
R Run(Arg1 a1) {
bool needs_delete = self_deleting_; // read in case callback deletes
R result = function_(a1);
if (needs_delete) delete this;
return result;
}
private:
FunctionType function_;
bool self_deleting_;
};
template<typename R, typename P1, typename A1>
class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> {
public:
typedef R (*FunctionType)(P1, A1);
FunctionResultCallback_1_1(FunctionType function, bool self_deleting,
P1 p1)
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
~FunctionResultCallback_1_1() {}
R Run(A1 a1) {
bool needs_delete = self_deleting_; // read in case callback deletes
R result = function_(p1_, a1);
if (needs_delete) delete this;
return result;
}
private:
FunctionType function_;
bool self_deleting_;
P1 p1_;
};
template <typename T>
struct InternalConstRef {
typedef typename std::remove_reference<T>::type base_type;
typedef const base_type& type;
};
template<typename R, typename T>
class MethodResultCallback_0_0 : public ResultCallback<R> {
public:
typedef R (T::*MethodType)();
MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting)
: object_(object),
method_(method),
self_deleting_(self_deleting) {}
~MethodResultCallback_0_0() {}
R Run() {
bool needs_delete = self_deleting_;
R result = (object_->*method_)();
if (needs_delete) delete this;
return result;
}
private:
T* object_;
MethodType method_;
bool self_deleting_;
};
template <typename R, typename T, typename P1, typename P2, typename P3,
typename P4, typename P5, typename A1, typename A2>
class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
public:
typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2);
MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting,
P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
: object_(object),
method_(method),
self_deleting_(self_deleting),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4),
p5_(p5) {}
~MethodResultCallback_5_2() {}
R Run(A1 a1, A2 a2) {
bool needs_delete = self_deleting_;
R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2);
if (needs_delete) delete this;
return result;
}
private:
T* object_;
MethodType method_;
bool self_deleting_;
typename std::remove_reference<P1>::type p1_;
typename std::remove_reference<P2>::type p2_;
typename std::remove_reference<P3>::type p3_;
typename std::remove_reference<P4>::type p4_;
typename std::remove_reference<P5>::type p5_;
};
} // namespace internal
// See Closure.
inline Closure* NewCallback(void (*function)()) {
return new internal::FunctionClosure0(function, true);
}
// See Closure.
inline Closure* NewPermanentCallback(void (*function)()) {
return new internal::FunctionClosure0(function, false);
}
// See Closure.
template <typename Class>
inline Closure* NewCallback(Class* object, void (Class::*method)()) {
return new internal::MethodClosure0<Class>(object, method, true);
}
// See Closure.
template <typename Class>
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) {
return new internal::MethodClosure0<Class>(object, method, false);
}
// See Closure.
template <typename Arg1>
inline Closure* NewCallback(void (*function)(Arg1),
Arg1 arg1) {
return new internal::FunctionClosure1<Arg1>(function, true, arg1);
}
// See Closure.
template <typename Arg1>
inline Closure* NewPermanentCallback(void (*function)(Arg1),
Arg1 arg1) {
return new internal::FunctionClosure1<Arg1>(function, false, arg1);
}
// See Closure.
template <typename Class, typename Arg1>
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1),
Arg1 arg1) {
return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1);
}
// See Closure.
template <typename Class, typename Arg1>
inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1),
Arg1 arg1) {
return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1);
}
// See Closure.
template <typename Arg1, typename Arg2>
inline Closure* NewCallback(void (*function)(Arg1, Arg2),
Arg1 arg1, Arg2 arg2) {
return new internal::FunctionClosure2<Arg1, Arg2>(
function, true, arg1, arg2);
}
// See Closure.
template <typename Arg1, typename Arg2>
inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2),
Arg1 arg1, Arg2 arg2) {
return new internal::FunctionClosure2<Arg1, Arg2>(
function, false, arg1, arg2);
}
// See Closure.
template <typename Class, typename Arg1, typename Arg2>
inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2),
Arg1 arg1, Arg2 arg2) {
return new internal::MethodClosure2<Class, Arg1, Arg2>(
object, method, true, arg1, arg2);
}
// See Closure.
template <typename Class, typename Arg1, typename Arg2>
inline Closure* NewPermanentCallback(
Class* object, void (Class::*method)(Arg1, Arg2),
Arg1 arg1, Arg2 arg2) {
return new internal::MethodClosure2<Class, Arg1, Arg2>(
object, method, false, arg1, arg2);
}
// See ResultCallback
template<typename R>
inline ResultCallback<R>* NewCallback(R (*function)()) {
return new internal::FunctionResultCallback_0_0<R>(function, true);
}
// See ResultCallback
template<typename R>
inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
return new internal::FunctionResultCallback_0_0<R>(function, false);
}
// See ResultCallback
template<typename R, typename P1>
inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
return new internal::FunctionResultCallback_1_0<R, P1>(
function, true, p1);
}
// See ResultCallback
template<typename R, typename P1>
inline ResultCallback<R>* NewPermanentCallback(
R (*function)(P1), P1 p1) {
return new internal::FunctionResultCallback_1_0<R, P1>(
function, false, p1);
}
// See ResultCallback1
template<typename R, typename A1>
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
return new internal::FunctionResultCallback_0_1<R, A1>(function, true);
}
// See ResultCallback1
template<typename R, typename A1>
inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) {
return new internal::FunctionResultCallback_0_1<R, A1>(function, false);
}
// See ResultCallback1
template<typename R, typename P1, typename A1>
inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) {
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
function, true, p1);
}
// See ResultCallback1
template<typename R, typename P1, typename A1>
inline ResultCallback1<R, A1>* NewPermanentCallback(
R (*function)(P1, A1), P1 p1) {
return new internal::FunctionResultCallback_1_1<R, P1, A1>(
function, false, p1);
}
// See MethodResultCallback_0_0
template <typename R, typename T1, typename T2>
inline ResultCallback<R>* NewPermanentCallback(
T1* object, R (T2::*function)()) {
return new internal::MethodResultCallback_0_0<R, T1>(object, function, false);
}
// See MethodResultCallback_5_2
template <typename R, typename T, typename P1, typename P2, typename P3,
typename P4, typename P5, typename A1, typename A2>
inline ResultCallback2<R, A1, A2>* NewPermanentCallback(
T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2),
typename internal::InternalConstRef<P1>::type p1,
typename internal::InternalConstRef<P2>::type p2,
typename internal::InternalConstRef<P3>::type p3,
typename internal::InternalConstRef<P4>::type p4,
typename internal::InternalConstRef<P5>::type p5) {
return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1,
A2>(object, function, false, p1,
p2, p3, p4, p5);
}
// A function which does nothing. Useful for creating no-op callbacks, e.g.:
// Closure* nothing = NewCallback(&DoNothing);
void LIBPROTOBUF_EXPORT DoNothing();
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_