summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gyp1
-rw-r--r--base/raw_scoped_refptr_mismatch_checker.h170
-rw-r--r--base/task.h12
3 files changed, 182 insertions, 1 deletions
diff --git a/base/base.gyp b/base/base.gyp
index 23b85b1..3373f5a 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -254,6 +254,7 @@
'rand_util.h',
'rand_util_posix.cc',
'rand_util_win.cc',
+ 'raw_scoped_refptr_mismatch_checker.h',
'ref_counted.cc',
'ref_counted.h',
'ref_counted_memory.h',
diff --git a/base/raw_scoped_refptr_mismatch_checker.h b/base/raw_scoped_refptr_mismatch_checker.h
new file mode 100644
index 0000000..598710f
--- /dev/null
+++ b/base/raw_scoped_refptr_mismatch_checker.h
@@ -0,0 +1,170 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
+#define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
+
+#include "base/ref_counted.h"
+#include "base/tuple.h"
+
+// It is dangerous to post a task with a raw pointer argument to a function
+// that expects a scoped_refptr<>. The compiler will happily accept the
+// situation, but it will not attempt to increase the refcount until the task
+// runs. Callers expecting the argument to be refcounted up at post time are
+// in for a nasty surprise! Example: http://crbug.com/27191
+// The following set of traits are designed to generate a compile error
+// whenever this antipattern is attempted.
+template <class A, class B>
+struct ExpectsScopedRefptrButGetsRawPtr {
+ enum { value = 0 };
+};
+
+template <class A, class B>
+struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> {
+ enum { value = 1 };
+};
+
+template <class Function, class Params>
+struct FunctionUsesScopedRefptrCorrectly {
+ enum { value = 1 };
+};
+
+template <class A1, class A2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > {
+ enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
+};
+
+template <class A1, class B1, class A2, class B2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
+};
+
+template <class A1, class B1, class C1, class A2, class B2, class C2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1),
+ Tuple3<A2, B2, C2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
+};
+
+template <class A1, class B1, class C1, class D1,
+ class A2, class B2, class C2, class D2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1),
+ Tuple4<A2, B2, C2, D2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
+};
+
+template <class A1, class B1, class C1, class D1, class E1,
+ class A2, class B2, class C2, class D2, class E2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1),
+ Tuple5<A2, B2, C2, D2, E2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
+};
+
+template <class A1, class B1, class C1, class D1, class E1, class F1,
+ class A2, class B2, class C2, class D2, class E2, class F2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1),
+ Tuple6<A2, B2, C2, D2, E2, F2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
+};
+
+template <class A1, class B1, class C1, class D1, class E1, class F1, class G1,
+ class A2, class B2, class C2, class D2, class E2, class F2, class G2>
+struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1),
+ Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
+};
+
+template <class Method, class Params>
+struct MethodUsesScopedRefptrCorrectly {
+ enum { value = 1 };
+};
+
+template <class T, class A1, class A2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > {
+ enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
+};
+
+template <class T, class A1, class B1, class A2, class B2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
+};
+
+template <class T, class A1, class B1, class C1,
+ class A2, class B2, class C2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1),
+ Tuple3<A2, B2, C2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
+};
+
+template <class T, class A1, class B1, class C1, class D1,
+ class A2, class B2, class C2, class D2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1),
+ Tuple4<A2, B2, C2, D2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
+};
+
+template <class T, class A1, class B1, class C1, class D1, class E1,
+ class A2, class B2, class C2, class D2, class E2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1),
+ Tuple5<A2, B2, C2, D2, E2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
+};
+
+template <class T, class A1, class B1, class C1, class D1, class E1, class F1,
+ class A2, class B2, class C2, class D2, class E2, class F2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1),
+ Tuple6<A2, B2, C2, D2, E2, F2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
+};
+
+template <class T,
+ class A1, class B1, class C1, class D1, class E1, class F1, class G1,
+ class A2, class B2, class C2, class D2, class E2, class F2, class G2>
+struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1),
+ Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
+ enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
+ ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
+};
+
+#endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
diff --git a/base/task.h b/base/task.h
index 0fb144b..7c2f393 100644
--- a/base/task.h
+++ b/base/task.h
@@ -6,6 +6,7 @@
#define BASE_TASK_H_
#include "base/non_thread_safe.h"
+#include "base/raw_scoped_refptr_mismatch_checker.h"
#include "base/tracked.h"
#include "base/tuple.h"
#include "base/weak_ptr.h"
@@ -140,6 +141,8 @@ class ScopedRunnableMethodFactory {
: obj_(obj),
meth_(meth),
params_(params) {
+ COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
+ badscopedrunnablemethodparams);
}
virtual void Run() {
@@ -273,6 +276,8 @@ class RunnableMethod : public CancelableTask {
RunnableMethod(T* obj, Method meth, const Params& params)
: obj_(obj), meth_(meth), params_(params) {
traits_.RetainCallee(obj_);
+ COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
+ badrunnablemethodparams);
}
~RunnableMethod() {
@@ -383,6 +388,8 @@ class RunnableFunction : public CancelableTask {
public:
RunnableFunction(Function function, const Params& params)
: function_(function), params_(params) {
+ COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value),
+ badrunnablefunctionparams);
}
~RunnableFunction() {
@@ -642,7 +649,10 @@ typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
template <class T, class Method, class Params>
class UnboundMethod {
public:
- UnboundMethod(Method m, Params p) : m_(m), p_(p) {}
+ UnboundMethod(Method m, Params p) : m_(m), p_(p) {
+ COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
+ badunboundmethodparams);
+ }
void Run(T* obj) const {
DispatchToMethod(obj, m_, p_);
}