Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Unified Diff: content/browser/cancelable_request.h

Issue 8068013: Add interface to CancelableRequest that allows use of base::Callback<>. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix dcheck Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/cancelable_request.h
diff --git a/content/browser/cancelable_request.h b/content/browser/cancelable_request.h
index a9e6f4fccef39e15db3564d3b7f24bfc4a2245bd..c6dbd07c59ad1ee86b1e5bc0911693f5a266f41d 100644
--- a/content/browser/cancelable_request.h
+++ b/content/browser/cancelable_request.h
@@ -91,6 +91,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
@@ -577,6 +578,20 @@ class CONTENT_EXPORT CancelableRequestBase
consumer_->WillExecute(provider_, handle_);
}
+ // Attempts to execute callback on |callback_thread_| if the request has not
+ // been canceled yet.
+ void DoForward(const base::Closure& forwarded_call, bool force_async) {
brettw 2011/10/01 16:26:12 This should be non-inline (the whole point of the
awong 2011/10/03 05:18:39 Done.
+ if (force_async || callback_thread_ != MessageLoop::current()) {
+ callback_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&CancelableRequestBase::ExecuteCallback, this,
+ forwarded_call));
+ } else {
+ // We can do synchronous callbacks when we're on the same thread.
+ ExecuteCallback(forwarded_call);
+ }
+ }
+
// The message loop that this request was created on. The callback will
// happen on the same thread.
MessageLoop* callback_thread_;
@@ -599,6 +614,26 @@ class CONTENT_EXPORT CancelableRequestBase
base::CancellationFlag canceled_;
private:
+ // Executes the |forwarded_call| and notifies the provider and the consumer
+ // that this request has been completed. This must be called on the
+ // |callback_thread_|.
+ void ExecuteCallback(const base::Closure& forwarded_call) {
brettw 2011/10/01 16:26:12 Ditto
awong 2011/10/03 05:18:39 Done.
+ DCHECK_EQ(callback_thread_, MessageLoop::current());
+
+ if (!canceled_.IsSet()) {
+ WillExecute();
+
+ // Execute the callback.
+ forwarded_call.Run();
+ }
+
+ // Notify the provider that the request is complete. The provider will
+ // notify the consumer for us. Note that it is possible for the callback to
+ // cancel this request; we must check canceled again.
+ if (!canceled_.IsSet())
+ NotifyCompleted();
+ }
+
DISALLOW_COPY_AND_ASSIGN(CancelableRequestBase);
};
@@ -631,6 +666,8 @@ class CONTENT_EXPORT CancelableRequestBase
template<typename CB>
class CancelableRequest : public CancelableRequestBase {
public:
+ // TODO(ajwong): After all calls have been migrated, remove this template in
+ // favor of the specialization on base::Callback<Sig>.
typedef CB CallbackType; // CallbackRunner<...>
typedef typename CB::TupleType TupleType; // Tuple of the callback args.
@@ -700,6 +737,235 @@ class CancelableRequest : public CancelableRequestBase {
scoped_ptr<CallbackType> callback_;
};
+// CancelableRequest<> wraps a normal base::Callback<> for use in the
+// CancelableRequest framework.
+//
+// When suing this class, the provider MUST call Init() (on the base class)
brettw 2011/10/01 16:26:12 suing -> using
awong 2011/10/03 05:18:39 Done.
+// before this is valid.
+//
+// The two functions ForwardResult(), and ForwardResultAsync() are used to
+// invoke the wrapped callback on the correct thread. They are the same
+// except that ForwardResult() will run the callback synchronously if
+// we are already on the right thread.
+//
+// The caller does not need to check for cancel before calling ForwardResult()
+// or ForwardResultAsync(). If the request has not been canceled, one of the
+// these MUST be called.
+//
+// If there are any pointers in the parameters, they must live at least as
+// long as the request so that it can be forwarded to the other thread.
+// For complex objects, this would typically be done by having a derived
+// request own the data itself.
+//
+// The following specializations handle different arities of base::Callbacks<>.
+template<>
+class CancelableRequest<base::Closure> : public CancelableRequestBase {
+ public:
+ typedef base::Closure CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(void) {
+ if (canceled()) return;
+ DoForward(callback_, false);
+ }
+
+ void ForwardResultAsync() {
+ if (canceled()) return;
+ DoForward(callback_, true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1>
+class CancelableRequest<base::Callback<void(A1)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1), false);
+ }
+
+ void ForwardResultAsync(const A1& a1) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1, typename A2>
+class CancelableRequest<base::Callback<void(A1,A2)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1,A2)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1, const A2& a2) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2), false);
+ }
+
+ void ForwardResultAsync(const A1& a1, const A2& a2) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1, typename A2, typename A3>
+class CancelableRequest<base::Callback<void(A1,A2,A3)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1,A2,A3)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1, const A2& a2, const A3& a3) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3), false);
+ }
+
+ void ForwardResultAsync(const A1& a1, const A2& a2, const A3& a3) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1, typename A2, typename A3, typename A4>
+class CancelableRequest<base::Callback<void(A1, A2, A3, A4)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1, A2, A3, A4)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4), false);
+ }
+
+ void ForwardResultAsync(const A1& a1, const A2& a2, const A3& a3,
+ const A4& a4) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1, typename A2, typename A3, typename A4, typename A5>
+class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1, A2, A3, A4, A5)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+ const A5& a5) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), false);
+ }
+
+ void ForwardResultAsync(const A1& a1, const A2& a2, const A3& a3,
+ const A4& a4, const A5& a5) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
+template<typename A1, typename A2, typename A3, typename A4, typename A5,
+ typename A6>
+class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5, A6)> > :
+ public CancelableRequestBase {
+ public:
+ typedef base::Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
+
+ explicit CancelableRequest(const CallbackType& callback)
+ : CancelableRequestBase(),
+ callback_(callback) {
+ DCHECK(!callback.is_null()) << "Callback must be initialized.";
+ }
+
+ void ForwardResult(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+ const A5& a5, const A6& a6) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), false);
+ }
+
+ void ForwardResultAsync(const A1& a1, const A2& a2, const A3& a3,
+ const A4& a4, const A5& a5, const A6& a6) {
+ if (canceled()) return;
+ DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), true);
+ }
+
+ protected:
+ virtual ~CancelableRequest() {}
+
+ private:
+ CallbackType callback_;
+};
+
// A CancelableRequest with a single value. This is intended for use when
// the provider provides a single value. The provider fills the result into
// the value, and notifies the request with a pointer to the value. For example,
« chrome/browser/icon_manager.h ('K') | « chrome/browser/ui/webui/fileicon_source.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698