mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Format include/base comments for Doxygen (see issue #3384)
This commit is contained in:
3
Doxyfile
3
Doxyfile
@ -1038,8 +1038,7 @@ EXCLUDE_PATTERNS = *_internal.h
|
|||||||
# Note that the wildcards are matched against the file with absolute path, so to
|
# Note that the wildcards are matched against the file with absolute path, so to
|
||||||
# exclude all test directories use the pattern */test/*
|
# exclude all test directories use the pattern */test/*
|
||||||
|
|
||||||
EXCLUDE_SYMBOLS = base::cef_internal \
|
EXCLUDE_SYMBOLS = base::cef_subtle \
|
||||||
base::cef_subtle \
|
|
||||||
base::internal \
|
base::internal \
|
||||||
cef_trace_event \
|
cef_trace_event \
|
||||||
cef::logging
|
cef::logging
|
||||||
|
@ -49,9 +49,11 @@
|
|||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// A flag that can safely be set from one thread and read from other threads.
|
///
|
||||||
//
|
/// A flag that can safely be set from one thread and read from other threads.
|
||||||
// This class IS NOT intended for synchronization between threads.
|
///
|
||||||
|
/// This class IS NOT intended for synchronization between threads.
|
||||||
|
///
|
||||||
class AtomicFlag {
|
class AtomicFlag {
|
||||||
public:
|
public:
|
||||||
AtomicFlag();
|
AtomicFlag();
|
||||||
@ -61,19 +63,26 @@ class AtomicFlag {
|
|||||||
|
|
||||||
~AtomicFlag();
|
~AtomicFlag();
|
||||||
|
|
||||||
// Set the flag. Must always be called from the same thread.
|
///
|
||||||
|
/// Set the flag. Must always be called from the same thread.
|
||||||
|
///
|
||||||
void Set();
|
void Set();
|
||||||
|
|
||||||
// Returns true iff the flag was set. If this returns true, the current thread
|
///
|
||||||
// is guaranteed to be synchronized with all memory operations on the thread
|
/// Returns true iff the flag was set. If this returns true, the current
|
||||||
// which invoked Set() up until at least the first call to Set() on it.
|
/// thread is guaranteed to be synchronized with all memory operations on the
|
||||||
|
/// thread which invoked Set() up until at least the first call to Set() on
|
||||||
|
/// it.
|
||||||
|
///
|
||||||
bool IsSet() const {
|
bool IsSet() const {
|
||||||
// Inline here: this has a measurable performance impact on base::WeakPtr.
|
// Inline here: this has a measurable performance impact on base::WeakPtr.
|
||||||
return flag_.load(std::memory_order_acquire) != 0;
|
return flag_.load(std::memory_order_acquire) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the flag. Be careful when using this: callers might not expect
|
///
|
||||||
// IsSet() to return false after returning true once.
|
/// Resets the flag. Be careful when using this: callers might not expect
|
||||||
|
/// IsSet() to return false after returning true once.
|
||||||
|
///
|
||||||
void UnsafeResetForTesting();
|
void UnsafeResetForTesting();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,19 +58,25 @@ class AtomicRefCount {
|
|||||||
explicit constexpr AtomicRefCount(int initial_value)
|
explicit constexpr AtomicRefCount(int initial_value)
|
||||||
: ref_count_(initial_value) {}
|
: ref_count_(initial_value) {}
|
||||||
|
|
||||||
// Increment a reference count.
|
///
|
||||||
// Returns the previous value of the count.
|
/// Increment a reference count.
|
||||||
|
/// Returns the previous value of the count.
|
||||||
|
///
|
||||||
int Increment() { return Increment(1); }
|
int Increment() { return Increment(1); }
|
||||||
|
|
||||||
// Increment a reference count by "increment", which must exceed 0.
|
///
|
||||||
// Returns the previous value of the count.
|
/// Increment a reference count by "increment", which must exceed 0.
|
||||||
|
/// Returns the previous value of the count.
|
||||||
|
///
|
||||||
int Increment(int increment) {
|
int Increment(int increment) {
|
||||||
return ref_count_.fetch_add(increment, std::memory_order_relaxed);
|
return ref_count_.fetch_add(increment, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement a reference count, and return whether the result is non-zero.
|
///
|
||||||
// Insert barriers to ensure that state written before the reference count
|
/// Decrement a reference count, and return whether the result is non-zero.
|
||||||
// became zero will be visible to a thread that has just made the count zero.
|
/// Insert barriers to ensure that state written before the reference count
|
||||||
|
/// became zero will be visible to a thread that has just made the count zero.
|
||||||
|
///
|
||||||
bool Decrement() {
|
bool Decrement() {
|
||||||
// TODO(jbroman): Technically this doesn't need to be an acquire operation
|
// TODO(jbroman): Technically this doesn't need to be an acquire operation
|
||||||
// unless the result is 1 (i.e., the ref count did indeed reach zero).
|
// unless the result is 1 (i.e., the ref count did indeed reach zero).
|
||||||
@ -79,23 +85,29 @@ class AtomicRefCount {
|
|||||||
return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
|
return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether the reference count is one. If the reference count is used
|
///
|
||||||
// in the conventional way, a refrerence count of 1 implies that the current
|
/// Return whether the reference count is one. If the reference count is used
|
||||||
// thread owns the reference and no other thread shares it. This call
|
/// in the conventional way, a refrerence count of 1 implies that the current
|
||||||
// performs the test for a reference count of one, and performs the memory
|
/// thread owns the reference and no other thread shares it. This call
|
||||||
// barrier needed for the owning thread to act on the object, knowing that it
|
/// performs the test for a reference count of one, and performs the memory
|
||||||
// has exclusive access to the object.
|
/// barrier needed for the owning thread to act on the object, knowing that it
|
||||||
|
/// has exclusive access to the object.
|
||||||
|
///
|
||||||
bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; }
|
bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; }
|
||||||
|
|
||||||
// Return whether the reference count is zero. With conventional object
|
///
|
||||||
// referencing counting, the object will be destroyed, so the reference count
|
/// Return whether the reference count is zero. With conventional object
|
||||||
// should never be zero. Hence this is generally used for a debug check.
|
/// referencing counting, the object will be destroyed, so the reference count
|
||||||
|
/// should never be zero. Hence this is generally used for a debug check.
|
||||||
|
///
|
||||||
bool IsZero() const {
|
bool IsZero() const {
|
||||||
return ref_count_.load(std::memory_order_acquire) == 0;
|
return ref_count_.load(std::memory_order_acquire) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current reference count (with no barriers). This is subtle, and
|
///
|
||||||
// should be used only for debugging.
|
/// Returns the current reference count (with no barriers). This is subtle,
|
||||||
|
/// and should be used only for debugging.
|
||||||
|
///
|
||||||
int SubtleRefCountForDebug() const {
|
int SubtleRefCountForDebug() const {
|
||||||
return ref_count_.load(std::memory_order_relaxed);
|
return ref_count_.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
@ -28,41 +28,42 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
///
|
||||||
// Usage documentation
|
/// \file
|
||||||
// -----------------------------------------------------------------------------
|
/// base::BindOnce() and base::BindRepeating() are helpers for creating
|
||||||
//
|
/// base::OnceCallback and base::RepeatingCallback objects respectively.
|
||||||
// Overview:
|
///
|
||||||
// base::BindOnce() and base::BindRepeating() are helpers for creating
|
/// For a runnable object of n-arity, the base::Bind*() family allows partial
|
||||||
// base::OnceCallback and base::RepeatingCallback objects respectively.
|
/// application of the first m arguments. The remaining n - m arguments must be
|
||||||
//
|
/// passed when invoking the callback with Run().
|
||||||
// For a runnable object of n-arity, the base::Bind*() family allows partial
|
///
|
||||||
// application of the first m arguments. The remaining n - m arguments must be
|
/// <pre>
|
||||||
// passed when invoking the callback with Run().
|
/// // The first argument is bound at callback creation; the remaining
|
||||||
//
|
/// // two must be passed when calling Run() on the callback object.
|
||||||
// // The first argument is bound at callback creation; the remaining
|
/// base::OnceCallback<long(int, long)> cb = base::BindOnce(
|
||||||
// // two must be passed when calling Run() on the callback object.
|
/// [](short x, int y, long z) { return x * y * z; }, 42);
|
||||||
// base::OnceCallback<long(int, long)> cb = base::BindOnce(
|
/// </pre>
|
||||||
// [](short x, int y, long z) { return x * y * z; }, 42);
|
///
|
||||||
//
|
/// When binding to a method, the receiver object must also be specified at
|
||||||
// When binding to a method, the receiver object must also be specified at
|
/// callback creation time. When Run() is invoked, the method will be invoked on
|
||||||
// callback creation time. When Run() is invoked, the method will be invoked on
|
/// the specified receiver object.
|
||||||
// the specified receiver object.
|
///
|
||||||
//
|
/// <pre>
|
||||||
// class C : public base::RefCounted<C> { void F(); };
|
/// class C : public base::RefCounted<C> { void F(); };
|
||||||
// auto instance = base::MakeRefCounted<C>();
|
/// auto instance = base::MakeRefCounted<C>();
|
||||||
// auto cb = base::BindOnce(&C::F, instance);
|
/// auto cb = base::BindOnce(&C::F, instance);
|
||||||
// std::move(cb).Run(); // Identical to instance->F()
|
/// std::move(cb).Run(); // Identical to instance->F()
|
||||||
//
|
/// </pre>
|
||||||
// See //docs/callback.md for the full documentation.
|
///
|
||||||
//
|
/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md
|
||||||
// -----------------------------------------------------------------------------
|
/// for the full documentation.
|
||||||
|
///
|
||||||
|
|
||||||
// Implementation notes
|
// Implementation notes
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
//
|
||||||
// If you're reading the implementation, before proceeding further, you should
|
// If you're reading the implementation, before proceeding further, you should
|
||||||
// read the top comment of base/internal/cef_bind_internal.h for a definition of
|
// read the top comment of base/internal/cef_bind_internal.h for a definition
|
||||||
// common terms and concepts.
|
// of common terms and concepts.
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_BIND_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_BIND_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_BIND_H_
|
#define CEF_INCLUDE_BASE_CEF_BIND_H_
|
||||||
@ -92,7 +93,9 @@
|
|||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// Bind as OnceCallback.
|
///
|
||||||
|
/// Bind as OnceCallback.
|
||||||
|
///
|
||||||
template <typename Functor, typename... Args>
|
template <typename Functor, typename... Args>
|
||||||
inline OnceCallback<internal::MakeUnboundRunType<Functor, Args...>> BindOnce(
|
inline OnceCallback<internal::MakeUnboundRunType<Functor, Args...>> BindOnce(
|
||||||
Functor&& functor,
|
Functor&& functor,
|
||||||
@ -111,7 +114,9 @@ inline OnceCallback<internal::MakeUnboundRunType<Functor, Args...>> BindOnce(
|
|||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind as RepeatingCallback.
|
///
|
||||||
|
/// Bind as RepeatingCallback.
|
||||||
|
///
|
||||||
template <typename Functor, typename... Args>
|
template <typename Functor, typename... Args>
|
||||||
inline RepeatingCallback<internal::MakeUnboundRunType<Functor, Args...>>
|
inline RepeatingCallback<internal::MakeUnboundRunType<Functor, Args...>>
|
||||||
BindRepeating(Functor&& functor, Args&&... args) {
|
BindRepeating(Functor&& functor, Args&&... args) {
|
||||||
@ -123,9 +128,11 @@ BindRepeating(Functor&& functor, Args&&... args) {
|
|||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special cases for binding to a base::Callback without extra bound arguments.
|
///
|
||||||
// We CHECK() the validity of callback to guard against null pointers
|
/// Special cases for binding to a base::Callback without extra bound arguments.
|
||||||
// accidentally ending up in posted tasks, causing hard-to-debug crashes.
|
/// We CHECK() the validity of callback to guard against null pointers
|
||||||
|
/// accidentally ending up in posted tasks, causing hard-to-debug crashes.
|
||||||
|
///
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
OnceCallback<Signature> BindOnce(OnceCallback<Signature> callback) {
|
OnceCallback<Signature> BindOnce(OnceCallback<Signature> callback) {
|
||||||
CHECK(callback);
|
CHECK(callback);
|
||||||
@ -145,44 +152,54 @@ RepeatingCallback<Signature> BindRepeating(
|
|||||||
return callback;
|
return callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unretained() allows binding a non-refcounted class, and to disable
|
///
|
||||||
// refcounting on arguments that are refcounted objects.
|
/// Unretained() allows binding a non-refcounted class, and to disable
|
||||||
//
|
/// refcounting on arguments that are refcounted objects.
|
||||||
// EXAMPLE OF Unretained():
|
///
|
||||||
//
|
/// EXAMPLE OF Unretained():
|
||||||
// class Foo {
|
///
|
||||||
// public:
|
/// <pre>
|
||||||
// void func() { cout << "Foo:f" << endl; }
|
/// class Foo {
|
||||||
// };
|
/// public:
|
||||||
//
|
/// void func() { cout << "Foo:f" << endl; }
|
||||||
// // In some function somewhere.
|
/// };
|
||||||
// Foo foo;
|
///
|
||||||
// OnceClosure foo_callback =
|
/// // In some function somewhere.
|
||||||
// BindOnce(&Foo::func, Unretained(&foo));
|
/// Foo foo;
|
||||||
// std::move(foo_callback).Run(); // Prints "Foo:f".
|
/// OnceClosure foo_callback =
|
||||||
//
|
/// BindOnce(&Foo::func, Unretained(&foo));
|
||||||
// Without the Unretained() wrapper on |&foo|, the above call would fail
|
/// std::move(foo_callback).Run(); // Prints "Foo:f".
|
||||||
// to compile because Foo does not support the AddRef() and Release() methods.
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// Without the Unretained() wrapper on |&foo|, the above call would fail
|
||||||
|
/// to compile because Foo does not support the AddRef() and Release() methods.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::UnretainedWrapper<T> Unretained(T* o) {
|
inline internal::UnretainedWrapper<T> Unretained(T* o) {
|
||||||
return internal::UnretainedWrapper<T>(o);
|
return internal::UnretainedWrapper<T>(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetainedRef() accepts a ref counted object and retains a reference to it.
|
///
|
||||||
// When the callback is called, the object is passed as a raw pointer.
|
/// RetainedRef() accepts a ref counted object and retains a reference to it.
|
||||||
//
|
/// When the callback is called, the object is passed as a raw pointer.
|
||||||
// EXAMPLE OF RetainedRef():
|
///
|
||||||
//
|
/// EXAMPLE OF RetainedRef():
|
||||||
// void foo(RefCountedBytes* bytes) {}
|
///
|
||||||
//
|
/// <pre>
|
||||||
// scoped_refptr<RefCountedBytes> bytes = ...;
|
/// void foo(RefCountedBytes* bytes) {}
|
||||||
// OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
|
///
|
||||||
// std::move(callback).Run();
|
/// scoped_refptr<RefCountedBytes> bytes = ...;
|
||||||
//
|
/// OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
|
||||||
// Without RetainedRef, the scoped_refptr would try to implicitly convert to
|
/// std::move(callback).Run();
|
||||||
// a raw pointer and fail compilation:
|
/// </pre>
|
||||||
//
|
///
|
||||||
// OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
|
/// Without RetainedRef, the scoped_refptr would try to implicitly convert to
|
||||||
|
/// a raw pointer and fail compilation:
|
||||||
|
///
|
||||||
|
/// <pre>
|
||||||
|
/// OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::RetainedRefWrapper<T> RetainedRef(T* o) {
|
inline internal::RetainedRefWrapper<T> RetainedRef(T* o) {
|
||||||
return internal::RetainedRefWrapper<T>(o);
|
return internal::RetainedRefWrapper<T>(o);
|
||||||
@ -192,26 +209,30 @@ inline internal::RetainedRefWrapper<T> RetainedRef(scoped_refptr<T> o) {
|
|||||||
return internal::RetainedRefWrapper<T>(std::move(o));
|
return internal::RetainedRefWrapper<T>(std::move(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owned() transfers ownership of an object to the callback resulting from
|
///
|
||||||
// bind; the object will be deleted when the callback is deleted.
|
/// Owned() transfers ownership of an object to the callback resulting from
|
||||||
//
|
/// bind; the object will be deleted when the callback is deleted.
|
||||||
// EXAMPLE OF Owned():
|
///
|
||||||
//
|
/// EXAMPLE OF Owned():
|
||||||
// void foo(int* arg) { cout << *arg << endl }
|
///
|
||||||
//
|
/// <pre>
|
||||||
// int* pn = new int(1);
|
/// void foo(int* arg) { cout << *arg << endl }
|
||||||
// RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
|
///
|
||||||
//
|
/// int* pn = new int(1);
|
||||||
// foo_callback.Run(); // Prints "1"
|
/// RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
|
||||||
// foo_callback.Run(); // Prints "1"
|
///
|
||||||
// *pn = 2;
|
/// foo_callback.Run(); // Prints "1"
|
||||||
// foo_callback.Run(); // Prints "2"
|
/// foo_callback.Run(); // Prints "1"
|
||||||
//
|
/// *pn = 2;
|
||||||
// foo_callback.Reset(); // |pn| is deleted. Also will happen when
|
/// foo_callback.Run(); // Prints "2"
|
||||||
// // |foo_callback| goes out of scope.
|
///
|
||||||
//
|
/// foo_callback.Reset(); // |pn| is deleted. Also will happen when
|
||||||
// Without Owned(), someone would have to know to delete |pn| when the last
|
/// // |foo_callback| goes out of scope.
|
||||||
// reference to the callback is deleted.
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// Without Owned(), someone would have to know to delete |pn| when the last
|
||||||
|
/// reference to the callback is deleted.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::OwnedWrapper<T> Owned(T* o) {
|
inline internal::OwnedWrapper<T> Owned(T* o) {
|
||||||
return internal::OwnedWrapper<T>(o);
|
return internal::OwnedWrapper<T>(o);
|
||||||
@ -223,78 +244,89 @@ inline internal::OwnedWrapper<T, Deleter> Owned(
|
|||||||
return internal::OwnedWrapper<T, Deleter>(std::move(ptr));
|
return internal::OwnedWrapper<T, Deleter>(std::move(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// OwnedRef() stores an object in the callback resulting from
|
///
|
||||||
// bind and passes a reference to the object to the bound function.
|
/// OwnedRef() stores an object in the callback resulting from
|
||||||
//
|
/// bind and passes a reference to the object to the bound function.
|
||||||
// EXAMPLE OF OwnedRef():
|
///
|
||||||
//
|
/// EXAMPLE OF OwnedRef():
|
||||||
// void foo(int& arg) { cout << ++arg << endl }
|
///
|
||||||
//
|
/// <pre>
|
||||||
// int counter = 0;
|
/// void foo(int& arg) { cout << ++arg << endl }
|
||||||
// RepeatingClosure foo_callback = BindRepeating(&foo, OwnedRef(counter));
|
///
|
||||||
//
|
/// int counter = 0;
|
||||||
// foo_callback.Run(); // Prints "1"
|
/// RepeatingClosure foo_callback = BindRepeating(&foo, OwnedRef(counter));
|
||||||
// foo_callback.Run(); // Prints "2"
|
///
|
||||||
// foo_callback.Run(); // Prints "3"
|
/// foo_callback.Run(); // Prints "1"
|
||||||
//
|
/// foo_callback.Run(); // Prints "2"
|
||||||
// cout << counter; // Prints "0", OwnedRef creates a copy of counter.
|
/// foo_callback.Run(); // Prints "3"
|
||||||
//
|
///
|
||||||
// Supports OnceCallbacks as well, useful to pass placeholder arguments:
|
/// cout << counter; // Prints "0", OwnedRef creates a copy of counter.
|
||||||
//
|
/// </pre>
|
||||||
// void bar(int& ignore, const std::string& s) { cout << s << endl }
|
///
|
||||||
//
|
/// Supports OnceCallbacks as well, useful to pass placeholder arguments:
|
||||||
// OnceClosure bar_callback = BindOnce(&bar, OwnedRef(0), "Hello");
|
///
|
||||||
//
|
/// <pre>
|
||||||
// std::move(bar_callback).Run(); // Prints "Hello"
|
/// void bar(int& ignore, const std::string& s) { cout << s << endl }
|
||||||
//
|
///
|
||||||
// Without OwnedRef() it would not be possible to pass a mutable reference to an
|
/// OnceClosure bar_callback = BindOnce(&bar, OwnedRef(0), "Hello");
|
||||||
// object owned by the callback.
|
///
|
||||||
|
/// std::move(bar_callback).Run(); // Prints "Hello"
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// Without OwnedRef() it would not be possible to pass a mutable reference to
|
||||||
|
/// an object owned by the callback.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
internal::OwnedRefWrapper<std::decay_t<T>> OwnedRef(T&& t) {
|
internal::OwnedRefWrapper<std::decay_t<T>> OwnedRef(T&& t) {
|
||||||
return internal::OwnedRefWrapper<std::decay_t<T>>(std::forward<T>(t));
|
return internal::OwnedRefWrapper<std::decay_t<T>>(std::forward<T>(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr)
|
///
|
||||||
// through a RepeatingCallback. Logically, this signifies a destructive transfer
|
/// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr)
|
||||||
// of the state of the argument into the target function. Invoking
|
/// through a RepeatingCallback. Logically, this signifies a destructive
|
||||||
// RepeatingCallback::Run() twice on a callback that was created with a Passed()
|
/// transfer of the state of the argument into the target function. Invoking
|
||||||
// argument will CHECK() because the first invocation would have already
|
/// RepeatingCallback::Run() twice on a callback that was created with a
|
||||||
// transferred ownership to the target function.
|
/// Passed() argument will CHECK() because the first invocation would have
|
||||||
//
|
/// already transferred ownership to the target function.
|
||||||
// Note that Passed() is not necessary with BindOnce(), as std::move() does the
|
///
|
||||||
// same thing. Avoid Passed() in favor of std::move() with BindOnce().
|
/// Note that Passed() is not necessary with BindOnce(), as std::move() does the
|
||||||
//
|
/// same thing. Avoid Passed() in favor of std::move() with BindOnce().
|
||||||
// EXAMPLE OF Passed():
|
///
|
||||||
//
|
/// EXAMPLE OF Passed():
|
||||||
// void TakesOwnership(std::unique_ptr<Foo> arg) { }
|
///
|
||||||
// std::unique_ptr<Foo> CreateFoo() { return std::make_unique<Foo>();
|
/// <pre>
|
||||||
// }
|
/// void TakesOwnership(std::unique_ptr<Foo> arg) { }
|
||||||
//
|
/// std::unique_ptr<Foo> CreateFoo() { return std::make_unique<Foo>();
|
||||||
// auto f = std::make_unique<Foo>();
|
/// }
|
||||||
//
|
///
|
||||||
// // |cb| is given ownership of Foo(). |f| is now NULL.
|
/// auto f = std::make_unique<Foo>();
|
||||||
// // You can use std::move(f) in place of &f, but it's more verbose.
|
///
|
||||||
// RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
|
/// // |cb| is given ownership of Foo(). |f| is now NULL.
|
||||||
//
|
/// // You can use std::move(f) in place of &f, but it's more verbose.
|
||||||
// // Run was never called so |cb| still owns Foo() and deletes
|
/// RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
|
||||||
// // it on Reset().
|
///
|
||||||
// cb.Reset();
|
/// // Run was never called so |cb| still owns Foo() and deletes
|
||||||
//
|
/// // it on Reset().
|
||||||
// // |cb| is given a new Foo created by CreateFoo().
|
/// cb.Reset();
|
||||||
// cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
|
///
|
||||||
//
|
/// // |cb| is given a new Foo created by CreateFoo().
|
||||||
// // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
|
/// cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
|
||||||
// // no longer owns Foo() and, if reset, would not delete Foo().
|
///
|
||||||
// cb.Run(); // Foo() is now transferred to |arg| and deleted.
|
/// // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
|
||||||
// cb.Run(); // This CHECK()s since Foo() already been used once.
|
/// // no longer owns Foo() and, if reset, would not delete Foo().
|
||||||
//
|
/// cb.Run(); // Foo() is now transferred to |arg| and deleted.
|
||||||
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is
|
/// cb.Run(); // This CHECK()s since Foo() already been used once.
|
||||||
// best suited for use with the return value of a function or other temporary
|
/// </pre>
|
||||||
// rvalues. The second takes a pointer to the scoper and is just syntactic sugar
|
///
|
||||||
// to avoid having to write Passed(std::move(scoper)).
|
/// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is
|
||||||
//
|
/// best suited for use with the return value of a function or other temporary
|
||||||
// Both versions of Passed() prevent T from being an lvalue reference. The first
|
/// rvalues. The second takes a pointer to the scoper and is just syntactic
|
||||||
// via use of enable_if, and the second takes a T* which will not bind to T&.
|
/// sugar to avoid having to write Passed(std::move(scoper)).
|
||||||
|
///
|
||||||
|
/// Both versions of Passed() prevent T from being an lvalue reference. The
|
||||||
|
/// first via use of enable_if, and the second takes a T* which will not bind to
|
||||||
|
/// T&.
|
||||||
|
///
|
||||||
template <typename T,
|
template <typename T,
|
||||||
std::enable_if_t<!std::is_lvalue_reference<T>::value>* = nullptr>
|
std::enable_if_t<!std::is_lvalue_reference<T>::value>* = nullptr>
|
||||||
inline internal::PassedWrapper<T> Passed(T&& scoper) {
|
inline internal::PassedWrapper<T> Passed(T&& scoper) {
|
||||||
@ -305,21 +337,25 @@ inline internal::PassedWrapper<T> Passed(T* scoper) {
|
|||||||
return internal::PassedWrapper<T>(std::move(*scoper));
|
return internal::PassedWrapper<T>(std::move(*scoper));
|
||||||
}
|
}
|
||||||
|
|
||||||
// IgnoreResult() is used to adapt a function or callback with a return type to
|
///
|
||||||
// one with a void return. This is most useful if you have a function with,
|
/// IgnoreResult() is used to adapt a function or callback with a return type to
|
||||||
// say, a pesky ignorable bool return that you want to use with PostTask or
|
/// one with a void return. This is most useful if you have a function with,
|
||||||
// something else that expect a callback with a void return.
|
/// say, a pesky ignorable bool return that you want to use with PostTask or
|
||||||
//
|
/// something else that expect a callback with a void return.
|
||||||
// EXAMPLE OF IgnoreResult():
|
///
|
||||||
//
|
/// EXAMPLE OF IgnoreResult():
|
||||||
// int DoSomething(int arg) { cout << arg << endl; }
|
///
|
||||||
//
|
/// <pre>
|
||||||
// // Assign to a callback with a void return type.
|
/// int DoSomething(int arg) { cout << arg << endl; }
|
||||||
// OnceCallback<void(int)> cb = BindOnce(IgnoreResult(&DoSomething));
|
///
|
||||||
// std::move(cb).Run(1); // Prints "1".
|
/// // Assign to a callback with a void return type.
|
||||||
//
|
/// OnceCallback<void(int)> cb = BindOnce(IgnoreResult(&DoSomething));
|
||||||
// // Prints "2" on |ml|.
|
/// std::move(cb).Run(1); // Prints "1".
|
||||||
// ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
|
///
|
||||||
|
/// // Prints "2" on |ml|.
|
||||||
|
/// ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
|
inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
|
||||||
return internal::IgnoreResultHelper<T>(std::move(data));
|
return internal::IgnoreResultHelper<T>(std::move(data));
|
||||||
@ -327,16 +363,20 @@ inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
|
|||||||
|
|
||||||
#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
|
#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
|
||||||
|
|
||||||
// RetainBlock() is used to adapt an Objective-C block when Automated Reference
|
///
|
||||||
// Counting (ARC) is disabled. This is unnecessary when ARC is enabled, as the
|
/// RetainBlock() is used to adapt an Objective-C block when Automated Reference
|
||||||
// BindOnce and BindRepeating already support blocks then.
|
/// Counting (ARC) is disabled. This is unnecessary when ARC is enabled, as the
|
||||||
//
|
/// BindOnce and BindRepeating already support blocks then.
|
||||||
// EXAMPLE OF RetainBlock():
|
///
|
||||||
//
|
/// EXAMPLE OF RetainBlock():
|
||||||
// // Wrap the block and bind it to a callback.
|
///
|
||||||
// OnceCallback<void(int)> cb =
|
/// <pre>
|
||||||
// BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
|
/// // Wrap the block and bind it to a callback.
|
||||||
// std::move(cb).Run(1); // Logs "1".
|
/// OnceCallback<void(int)> cb =
|
||||||
|
/// BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
|
||||||
|
/// std::move(cb).Run(1); // Logs "1".
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <typename R, typename... Args>
|
template <typename R, typename... Args>
|
||||||
base::mac::ScopedBlock<R (^)(Args...)> RetainBlock(R (^block)(Args...)) {
|
base::mac::ScopedBlock<R (^)(Args...)> RetainBlock(R (^block)(Args...)) {
|
||||||
return base::mac::ScopedBlock<R (^)(Args...)>(block,
|
return base::mac::ScopedBlock<R (^)(Args...)>(block,
|
||||||
|
@ -27,36 +27,40 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// This file adds defines about the platform we're currently building on.
|
/// \file
|
||||||
//
|
/// This file adds defines about the platform we're currently building on.
|
||||||
// Operating System:
|
///
|
||||||
// OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
|
/// <pre>
|
||||||
// OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
|
/// Operating System:
|
||||||
// OS_QNX / OS_SOLARIS / OS_WIN
|
/// OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
|
||||||
// Operating System family:
|
/// OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
|
||||||
// OS_APPLE: IOS or MAC
|
/// OS_QNX / OS_SOLARIS / OS_WIN
|
||||||
// OS_BSD: FREEBSD or NETBSD or OPENBSD
|
/// Operating System family:
|
||||||
// OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
|
/// OS_APPLE: IOS or MAC
|
||||||
// or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
|
/// OS_BSD: FREEBSD or NETBSD or OPENBSD
|
||||||
//
|
/// OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
|
||||||
// /!\ Note: OS_CHROMEOS is set by the build system, not this file
|
/// or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
|
||||||
//
|
///
|
||||||
// Compiler:
|
/// /!\ Note: OS_CHROMEOS is set by the build system, not this file
|
||||||
// COMPILER_MSVC / COMPILER_GCC
|
///
|
||||||
//
|
/// Compiler:
|
||||||
// Processor:
|
/// COMPILER_MSVC / COMPILER_GCC
|
||||||
// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
|
///
|
||||||
// ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
|
/// Processor:
|
||||||
// ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
|
/// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
|
||||||
// Processor family:
|
/// ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
|
||||||
// ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
|
/// ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
|
||||||
// ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
|
/// Processor family:
|
||||||
// ARCH_CPU_PPC64_FAMILY: PPC64
|
/// ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
|
||||||
// ARCH_CPU_S390_FAMILY: S390 or S390X
|
/// ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
|
||||||
// ARCH_CPU_X86_FAMILY: X86 or X86_64
|
/// ARCH_CPU_PPC64_FAMILY: PPC64
|
||||||
// Processor features:
|
/// ARCH_CPU_S390_FAMILY: S390 or S390X
|
||||||
// ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
|
/// ARCH_CPU_X86_FAMILY: X86 or X86_64
|
||||||
// ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
|
/// Processor features:
|
||||||
|
/// ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
|
||||||
|
/// ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_BUILD_H_
|
#define CEF_INCLUDE_BASE_CEF_BUILD_H_
|
||||||
|
@ -28,40 +28,38 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
/// \file
|
||||||
// Usage documentation
|
/// A callback is similar in concept to a function pointer: it wraps a runnable
|
||||||
// -----------------------------------------------------------------------------
|
/// object such as a function, method, lambda, or even another callback,
|
||||||
//
|
/// allowing the runnable object to be invoked later via the callback object.
|
||||||
// Overview:
|
///
|
||||||
// A callback is similar in concept to a function pointer: it wraps a runnable
|
/// Unlike function pointers, callbacks are created with base::BindOnce() or
|
||||||
// object such as a function, method, lambda, or even another callback, allowing
|
/// base::BindRepeating() and support partial function application.
|
||||||
// the runnable object to be invoked later via the callback object.
|
///
|
||||||
//
|
/// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback
|
||||||
// Unlike function pointers, callbacks are created with base::BindOnce() or
|
/// may be Run() any number of times. |is_null()| is guaranteed to return true
|
||||||
// base::BindRepeating() and support partial function application.
|
/// for a moved-from callback.
|
||||||
//
|
///
|
||||||
// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback may
|
/// <pre>
|
||||||
// be Run() any number of times. |is_null()| is guaranteed to return true for a
|
/// // The lambda takes two arguments, but the first argument |x| is bound at
|
||||||
// moved-from callback.
|
/// // callback creation.
|
||||||
//
|
/// base::OnceCallback<int(int)> cb = base::BindOnce([] (int x, int y) {
|
||||||
// // The lambda takes two arguments, but the first argument |x| is bound at
|
/// return x + y;
|
||||||
// // callback creation.
|
/// }, 1);
|
||||||
// base::OnceCallback<int(int)> cb = base::BindOnce([] (int x, int y) {
|
/// // Run() only needs the remaining unbound argument |y|.
|
||||||
// return x + y;
|
/// printf("1 + 2 = %d\n", std::move(cb).Run(2)); // Prints 3
|
||||||
// }, 1);
|
/// printf("cb is null? %s\n",
|
||||||
// // Run() only needs the remaining unbound argument |y|.
|
/// cb.is_null() ? "true" : "false"); // Prints true
|
||||||
// printf("1 + 2 = %d\n", std::move(cb).Run(2)); // Prints 3
|
/// std::move(cb).Run(2); // Crashes since |cb| has already run.
|
||||||
// printf("cb is null? %s\n",
|
/// </pre>
|
||||||
// cb.is_null() ? "true" : "false"); // Prints true
|
///
|
||||||
// std::move(cb).Run(2); // Crashes since |cb| has already run.
|
/// Callbacks also support cancellation. A common use is binding the receiver
|
||||||
//
|
/// object as a WeakPtr<T>. If that weak pointer is invalidated, calling Run()
|
||||||
// Callbacks also support cancellation. A common use is binding the receiver
|
/// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct:
|
||||||
// object as a WeakPtr<T>. If that weak pointer is invalidated, calling Run()
|
/// simply cancelling a callback will not also make it null.
|
||||||
// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct:
|
///
|
||||||
// simply cancelling a callback will not also make it null.
|
/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md
|
||||||
//
|
/// for the full documentation.
|
||||||
// See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/callback.md
|
|
||||||
// for the full documentation.
|
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
#define CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
||||||
|
@ -48,9 +48,11 @@ class OnceCallback;
|
|||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
class RepeatingCallback;
|
class RepeatingCallback;
|
||||||
|
|
||||||
// Syntactic sugar to make OnceClosure<void()> and RepeatingClosure<void()>
|
///
|
||||||
// easier to declare since they will be used in a lot of APIs with delayed
|
/// Syntactic sugar to make OnceClosure<void()> and RepeatingClosure<void()>
|
||||||
// execution.
|
/// easier to declare since they will be used in a lot of APIs with delayed
|
||||||
|
/// execution.
|
||||||
|
///
|
||||||
using OnceClosure = OnceCallback<void()>;
|
using OnceClosure = OnceCallback<void()>;
|
||||||
using RepeatingClosure = RepeatingCallback<void()>;
|
using RepeatingClosure = RepeatingCallback<void()>;
|
||||||
|
|
||||||
|
@ -75,24 +75,32 @@ struct IsOnceCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// IsBaseCallback<T>::value is true when T is any of the Closure or Callback
|
///
|
||||||
// family of types.
|
/// IsBaseCallback<T>::value is true when T is any of the Closure or Callback
|
||||||
|
/// family of types.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>;
|
using IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>;
|
||||||
|
|
||||||
// IsOnceCallback<T>::value is true when T is a OnceClosure or OnceCallback
|
///
|
||||||
// type.
|
/// IsOnceCallback<T>::value is true when T is a OnceClosure or OnceCallback
|
||||||
|
/// type.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using IsOnceCallback = internal::IsOnceCallbackImpl<std::decay_t<T>>;
|
using IsOnceCallback = internal::IsOnceCallbackImpl<std::decay_t<T>>;
|
||||||
|
|
||||||
// SFINAE friendly enabler allowing to overload methods for both Repeating and
|
///
|
||||||
// OnceCallbacks.
|
/// SFINAE friendly enabler allowing to overload methods for both Repeating and
|
||||||
//
|
/// OnceCallbacks.
|
||||||
// Usage:
|
///
|
||||||
// template <template <typename> class CallbackType,
|
/// Usage:
|
||||||
// ... other template args ...,
|
/// <pre>
|
||||||
// typename = EnableIfIsBaseCallback<CallbackType>>
|
/// template <template <typename> class CallbackType,
|
||||||
// void DoStuff(CallbackType<...> cb, ...);
|
/// ... other template args ...,
|
||||||
|
/// typename = EnableIfIsBaseCallback<CallbackType>>
|
||||||
|
/// void DoStuff(CallbackType<...> cb, ...);
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <template <typename> class CallbackType>
|
template <template <typename> class CallbackType>
|
||||||
using EnableIfIsBaseCallback =
|
using EnableIfIsBaseCallback =
|
||||||
std::enable_if_t<IsBaseCallback<CallbackType<void()>>::value>;
|
std::enable_if_t<IsBaseCallback<CallbackType<void()>>::value>;
|
||||||
@ -129,13 +137,16 @@ class OnceCallbackHolder final {
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// Wraps the given OnceCallback into a RepeatingCallback that relays its
|
///
|
||||||
// invocation to the original OnceCallback on the first invocation. The
|
/// Wraps the given OnceCallback into a RepeatingCallback that relays its
|
||||||
// following invocations are just ignored.
|
/// invocation to the original OnceCallback on the first invocation. The
|
||||||
//
|
/// following invocations are just ignored.
|
||||||
// Note that this deliberately subverts the Once/Repeating paradigm of Callbacks
|
///
|
||||||
// but helps ease the migration from old-style Callbacks. Avoid if possible; use
|
/// Note that this deliberately subverts the Once/Repeating paradigm of
|
||||||
// if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593
|
/// Callbacks but helps ease the migration from old-style Callbacks. Avoid if
|
||||||
|
/// possible; use if necessary for migration.
|
||||||
|
///
|
||||||
|
// TODO(tzik): Remove it. https://crbug.com/730593
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
|
RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
|
||||||
OnceCallback<void(Args...)> callback) {
|
OnceCallback<void(Args...)> callback) {
|
||||||
@ -145,9 +156,11 @@ RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
|
|||||||
/*ignore_extra_runs=*/true));
|
/*ignore_extra_runs=*/true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps the given OnceCallback and returns two OnceCallbacks with an identical
|
///
|
||||||
// signature. On first invokation of either returned callbacks, the original
|
/// Wraps the given OnceCallback and returns two OnceCallbacks with an identical
|
||||||
// callback is invoked. Invoking the remaining callback results in a crash.
|
/// signature. On first invokation of either returned callbacks, the original
|
||||||
|
/// callback is invoked. Invoking the remaining callback results in a crash.
|
||||||
|
///
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
|
std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
|
||||||
SplitOnceCallback(OnceCallback<void(Args...)> callback) {
|
SplitOnceCallback(OnceCallback<void(Args...)> callback) {
|
||||||
@ -158,10 +171,12 @@ SplitOnceCallback(OnceCallback<void(Args...)> callback) {
|
|||||||
return std::make_pair(wrapped_once, wrapped_once);
|
return std::make_pair(wrapped_once, wrapped_once);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
|
///
|
||||||
// that the Closure is executed no matter how the current scope exits.
|
/// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
|
||||||
// If you are looking for "ScopedCallback", "CallbackRunner", or
|
/// that the Closure is executed no matter how the current scope exits.
|
||||||
// "CallbackScoper" this is the class you want.
|
/// If you are looking for "ScopedCallback", "CallbackRunner", or
|
||||||
|
/// "CallbackScoper" this is the class you want.
|
||||||
|
///
|
||||||
class ScopedClosureRunner {
|
class ScopedClosureRunner {
|
||||||
public:
|
public:
|
||||||
ScopedClosureRunner();
|
ScopedClosureRunner();
|
||||||
@ -189,7 +204,9 @@ class ScopedClosureRunner {
|
|||||||
OnceClosure closure_;
|
OnceClosure closure_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a null callback.
|
///
|
||||||
|
/// Creates a null callback.
|
||||||
|
///
|
||||||
class NullCallback {
|
class NullCallback {
|
||||||
public:
|
public:
|
||||||
template <typename R, typename... Args>
|
template <typename R, typename... Args>
|
||||||
@ -202,7 +219,9 @@ class NullCallback {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a callback that does nothing when called.
|
///
|
||||||
|
/// Creates a callback that does nothing when called.
|
||||||
|
///
|
||||||
class DoNothing {
|
class DoNothing {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -225,9 +244,11 @@ class DoNothing {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Useful for creating a Closure that will delete a pointer when invoked. Only
|
///
|
||||||
// use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
|
/// Useful for creating a Closure that will delete a pointer when invoked. Only
|
||||||
// fit.
|
/// use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
|
||||||
|
/// fit.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DeletePointer(T* obj) {
|
void DeletePointer(T* obj) {
|
||||||
delete obj;
|
delete obj;
|
||||||
|
@ -28,54 +28,57 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// OVERVIEW:
|
///
|
||||||
//
|
/// \file
|
||||||
// A container for a list of callbacks. Provides callers the ability to manually
|
/// A container for a list of callbacks. Provides callers the ability to
|
||||||
// or automatically unregister callbacks at any time, including during callback
|
/// manually or automatically unregister callbacks at any time, including during
|
||||||
// notification.
|
/// callback notification.
|
||||||
//
|
///
|
||||||
// TYPICAL USAGE:
|
/// TYPICAL USAGE:
|
||||||
//
|
///
|
||||||
// class MyWidget {
|
/// <pre>
|
||||||
// public:
|
/// class MyWidget {
|
||||||
// using CallbackList = base::RepeatingCallbackList<void(const Foo&)>;
|
/// public:
|
||||||
//
|
/// using CallbackList = base::RepeatingCallbackList<void(const Foo&)>;
|
||||||
// // Registers |cb| to be called whenever NotifyFoo() is executed.
|
///
|
||||||
// CallbackListSubscription RegisterCallback(CallbackList::CallbackType cb) {
|
/// // Registers |cb| to be called whenever NotifyFoo() is executed.
|
||||||
// return callback_list_.Add(std::move(cb));
|
/// CallbackListSubscription RegisterCallback(CallbackList::CallbackType cb) {
|
||||||
// }
|
/// return callback_list_.Add(std::move(cb));
|
||||||
//
|
/// }
|
||||||
// private:
|
///
|
||||||
// // Calls all registered callbacks, with |foo| as the supplied arg.
|
/// private:
|
||||||
// void NotifyFoo(const Foo& foo) {
|
/// // Calls all registered callbacks, with |foo| as the supplied arg.
|
||||||
// callback_list_.Notify(foo);
|
/// void NotifyFoo(const Foo& foo) {
|
||||||
// }
|
/// callback_list_.Notify(foo);
|
||||||
//
|
/// }
|
||||||
// CallbackList callback_list_;
|
///
|
||||||
// };
|
/// CallbackList callback_list_;
|
||||||
//
|
/// };
|
||||||
//
|
///
|
||||||
// class MyWidgetListener {
|
///
|
||||||
// private:
|
/// class MyWidgetListener {
|
||||||
// void OnFoo(const Foo& foo) {
|
/// private:
|
||||||
// // Called whenever MyWidget::NotifyFoo() is executed, unless
|
/// void OnFoo(const Foo& foo) {
|
||||||
// // |foo_subscription_| has been destroyed.
|
/// // Called whenever MyWidget::NotifyFoo() is executed, unless
|
||||||
// }
|
/// // |foo_subscription_| has been destroyed.
|
||||||
//
|
/// }
|
||||||
// // Automatically deregisters the callback when deleted (e.g. in
|
///
|
||||||
// // ~MyWidgetListener()). Unretained(this) is safe here since the
|
/// // Automatically deregisters the callback when deleted (e.g. in
|
||||||
// // ScopedClosureRunner does not outlive |this|.
|
/// // ~MyWidgetListener()). Unretained(this) is safe here since the
|
||||||
// CallbackListSubscription foo_subscription_ =
|
/// // ScopedClosureRunner does not outlive |this|.
|
||||||
// MyWidget::Get()->RegisterCallback(
|
/// CallbackListSubscription foo_subscription_ =
|
||||||
// base::BindRepeating(&MyWidgetListener::OnFoo,
|
/// MyWidget::Get()->RegisterCallback(
|
||||||
// base::Unretained(this)));
|
/// base::BindRepeating(&MyWidgetListener::OnFoo,
|
||||||
// };
|
/// base::Unretained(this)));
|
||||||
//
|
/// };
|
||||||
// UNSUPPORTED:
|
/// </pre>
|
||||||
//
|
///
|
||||||
// * Destroying the CallbackList during callback notification.
|
/// UNSUPPORTED:
|
||||||
//
|
///
|
||||||
// This is possible to support, but not currently necessary.
|
/// * Destroying the CallbackList during callback notification.
|
||||||
|
///
|
||||||
|
/// This is possible to support, but not currently necessary.
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
#define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
||||||
@ -381,9 +384,9 @@ class RepeatingCallbackList
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Syntactic sugar to parallel that used for Callbacks.
|
///
|
||||||
// ClosureList explicitly not provided since it is not used, and CallbackList
|
/// Syntactic sugar to parallel that used for Callbacks.
|
||||||
// is deprecated. {Once,Repeating}ClosureList should instead be used.
|
///
|
||||||
using OnceClosureList = OnceCallbackList<void()>;
|
using OnceClosureList = OnceCallbackList<void()>;
|
||||||
using RepeatingClosureList = RepeatingCallbackList<void()>;
|
using RepeatingClosureList = RepeatingCallbackList<void()>;
|
||||||
|
|
||||||
|
@ -28,44 +28,51 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// CancelableCallback is a wrapper around base::Callback that allows
|
///
|
||||||
// cancellation of a callback. CancelableCallback takes a reference on the
|
/// \file
|
||||||
// wrapped callback until this object is destroyed or Reset()/Cancel() are
|
/// CancelableCallback is a wrapper around base::Callback that allows
|
||||||
// called.
|
/// cancellation of a callback. CancelableCallback takes a reference on the
|
||||||
//
|
/// wrapped callback until this object is destroyed or Reset()/Cancel() are
|
||||||
// NOTE:
|
/// called.
|
||||||
//
|
///
|
||||||
// Calling CancelableCallback::Cancel() brings the object back to its natural,
|
/// NOTE:
|
||||||
// default-constructed state, i.e., CancelableCallback::callback() will return
|
///
|
||||||
// a null callback.
|
/// Calling CancelableCallback::Cancel() brings the object back to its natural,
|
||||||
//
|
/// default-constructed state, i.e., CancelableCallback::callback() will return
|
||||||
// THREAD-SAFETY:
|
/// a null callback.
|
||||||
//
|
///
|
||||||
// CancelableCallback objects must be created on, posted to, cancelled on, and
|
/// THREAD-SAFETY:
|
||||||
// destroyed on the same thread.
|
///
|
||||||
//
|
/// CancelableCallback objects must be created on, posted to, cancelled on, and
|
||||||
//
|
/// destroyed on the same thread.
|
||||||
// EXAMPLE USAGE:
|
///
|
||||||
//
|
///
|
||||||
// In the following example, the test is verifying that RunIntensiveTest()
|
/// EXAMPLE USAGE:
|
||||||
// Quit()s the message loop within 4 seconds. The cancelable callback is posted
|
///
|
||||||
// to the message loop, the intensive test runs, the message loop is run,
|
/// In the following example, the test is verifying that RunIntensiveTest()
|
||||||
// then the callback is cancelled.
|
/// Quit()s the message loop within 4 seconds. The cancelable callback is posted
|
||||||
//
|
/// to the message loop, the intensive test runs, the message loop is run,
|
||||||
// RunLoop run_loop;
|
/// then the callback is cancelled.
|
||||||
//
|
///
|
||||||
// void TimeoutCallback(const std::string& timeout_message) {
|
/// <pre>
|
||||||
// FAIL() << timeout_message;
|
/// RunLoop run_loop;
|
||||||
// run_loop.QuitWhenIdle();
|
///
|
||||||
// }
|
/// void TimeoutCallback(const std::string& timeout_message) {
|
||||||
//
|
/// FAIL() << timeout_message;
|
||||||
// CancelableOnceClosure timeout(
|
/// run_loop.QuitWhenIdle();
|
||||||
// base::BindOnce(&TimeoutCallback, "Test timed out."));
|
/// }
|
||||||
// ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, timeout.callback(),
|
///
|
||||||
// TimeDelta::FromSeconds(4));
|
/// CancelableOnceClosure timeout(
|
||||||
// RunIntensiveTest();
|
/// base::BindOnce(&TimeoutCallback, "Test timed out."));
|
||||||
// run_loop.Run();
|
/// ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
|
||||||
// timeout.Cancel(); // Hopefully this is hit before the timeout callback runs.
|
/// timeout.callback(),
|
||||||
|
/// TimeDelta::FromSeconds(4));
|
||||||
|
/// RunIntensiveTest();
|
||||||
|
/// run_loop.Run();
|
||||||
|
/// // Hopefully this is hit before the timeout callback runs.
|
||||||
|
/// timeout.Cancel();
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
#define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
||||||
@ -166,8 +173,10 @@ class CancelableCallbackImpl {
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// Consider using base::WeakPtr directly instead of base::CancelableCallback for
|
///
|
||||||
// the task cancellation.
|
/// Consider using base::WeakPtr directly instead of base::CancelableCallback
|
||||||
|
/// for the task cancellation.
|
||||||
|
///
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
using CancelableOnceCallback =
|
using CancelableOnceCallback =
|
||||||
internal::CancelableCallbackImpl<OnceCallback<Signature>>;
|
internal::CancelableCallbackImpl<OnceCallback<Signature>>;
|
||||||
|
@ -47,9 +47,11 @@
|
|||||||
namespace base {
|
namespace base {
|
||||||
namespace cef_internal {
|
namespace cef_internal {
|
||||||
|
|
||||||
// A convenient wrapper for an OS specific critical section. The only real
|
///
|
||||||
// intelligence in this class is in debug mode for the support for the
|
/// A convenient wrapper for an OS specific critical section. The only real
|
||||||
// AssertAcquired() method.
|
/// intelligence in this class is in debug mode for the support for the
|
||||||
|
/// AssertAcquired() method.
|
||||||
|
///
|
||||||
class Lock {
|
class Lock {
|
||||||
public:
|
public:
|
||||||
#if !DCHECK_IS_ON() // Optimized wrapper implementation
|
#if !DCHECK_IS_ON() // Optimized wrapper implementation
|
||||||
@ -62,10 +64,12 @@ class Lock {
|
|||||||
void Acquire() { lock_.Lock(); }
|
void Acquire() { lock_.Lock(); }
|
||||||
void Release() { lock_.Unlock(); }
|
void Release() { lock_.Unlock(); }
|
||||||
|
|
||||||
// If the lock is not held, take it and return true. If the lock is already
|
///
|
||||||
// held by another thread, immediately return false. This must not be called
|
/// If the lock is not held, take it and return true. If the lock is already
|
||||||
// by a thread already holding the lock (what happens is undefined and an
|
/// held by another thread, immediately return false. This must not be called
|
||||||
// assertion may fail).
|
/// by a thread already holding the lock (what happens is undefined and an
|
||||||
|
/// assertion may fail).
|
||||||
|
///
|
||||||
bool Try() { return lock_.Try(); }
|
bool Try() { return lock_.Try(); }
|
||||||
|
|
||||||
// Null implementation if not debug.
|
// Null implementation if not debug.
|
||||||
@ -116,7 +120,9 @@ class Lock {
|
|||||||
LockImpl lock_;
|
LockImpl lock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A helper class that acquires the given Lock while the AutoLock is in scope.
|
///
|
||||||
|
/// A helper class that acquires the given Lock while the AutoLock is in scope.
|
||||||
|
///
|
||||||
class AutoLock {
|
class AutoLock {
|
||||||
public:
|
public:
|
||||||
struct AlreadyAcquired {};
|
struct AlreadyAcquired {};
|
||||||
@ -139,8 +145,10 @@ class AutoLock {
|
|||||||
Lock& lock_;
|
Lock& lock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// AutoUnlock is a helper that will Release() the |lock| argument in the
|
///
|
||||||
// constructor, and re-Acquire() it in the destructor.
|
/// AutoUnlock is a helper that will Release() the |lock| argument in the
|
||||||
|
/// constructor, and re-Acquire() it in the destructor.
|
||||||
|
///
|
||||||
class AutoUnlock {
|
class AutoUnlock {
|
||||||
public:
|
public:
|
||||||
explicit AutoUnlock(Lock& lock) : lock_(lock) {
|
explicit AutoUnlock(Lock& lock) : lock_(lock) {
|
||||||
|
@ -27,110 +27,130 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// ---------------------------------------------------------------------------
|
///
|
||||||
//
|
/// \file
|
||||||
// The contents of this file are only available to applications that link
|
/// A bunch of macros for logging.
|
||||||
// against the libcef_dll_wrapper target.
|
///
|
||||||
//
|
/// NOTE: The contents of this file are only available to applications that link
|
||||||
// WARNING: Logging macros should not be used in the main/browser process before
|
/// against the libcef_dll_wrapper target.
|
||||||
// calling CefInitialize or in sub-processes before calling CefExecuteProcess.
|
///
|
||||||
//
|
/// WARNING: Logging macros should not be used in the main/browser process
|
||||||
// Instructions
|
/// before calling CefInitialize or in sub-processes before calling
|
||||||
// ------------
|
/// CefExecuteProcess.
|
||||||
//
|
///
|
||||||
// Make a bunch of macros for logging. The way to log things is to stream
|
/// INSTRUCTIONS:
|
||||||
// things to LOG(<a particular severity level>). E.g.,
|
///
|
||||||
//
|
/// The way to log things is to stream things to LOG(<a particular severity
|
||||||
// LOG(INFO) << "Found " << num_cookies << " cookies";
|
/// level>). E.g.,
|
||||||
//
|
///
|
||||||
// You can also do conditional logging:
|
/// <pre>
|
||||||
//
|
/// LOG(INFO) << "Found " << num_cookies << " cookies";
|
||||||
// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
/// </pre>
|
||||||
//
|
///
|
||||||
// The CHECK(condition) macro is active in both debug and release builds and
|
/// You can also do conditional logging:
|
||||||
// effectively performs a LOG(FATAL) which terminates the process and
|
///
|
||||||
// generates a crashdump unless a debugger is attached.
|
/// <pre>
|
||||||
//
|
/// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
||||||
// There are also "debug mode" logging macros like the ones above:
|
/// </pre>
|
||||||
//
|
///
|
||||||
// DLOG(INFO) << "Found cookies";
|
/// The CHECK(condition) macro is active in both debug and release builds and
|
||||||
//
|
/// effectively performs a LOG(FATAL) which terminates the process and
|
||||||
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
/// generates a crashdump unless a debugger is attached.
|
||||||
//
|
///
|
||||||
// All "debug mode" logging is compiled away to nothing for non-debug mode
|
/// There are also "debug mode" logging macros like the ones above:
|
||||||
// compiles. LOG_IF and development flags also work well together
|
///
|
||||||
// because the code can be compiled away sometimes.
|
/// <pre>
|
||||||
//
|
/// DLOG(INFO) << "Found cookies";
|
||||||
// We also have
|
///
|
||||||
//
|
/// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
||||||
// LOG_ASSERT(assertion);
|
/// </pre>
|
||||||
// DLOG_ASSERT(assertion);
|
///
|
||||||
//
|
/// All "debug mode" logging is compiled away to nothing for non-debug mode
|
||||||
// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
|
/// compiles. LOG_IF and development flags also work well together
|
||||||
//
|
/// because the code can be compiled away sometimes.
|
||||||
// There are "verbose level" logging macros. They look like
|
///
|
||||||
//
|
/// We also have
|
||||||
// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
|
///
|
||||||
// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
|
/// <pre>
|
||||||
//
|
/// LOG_ASSERT(assertion);
|
||||||
// These always log at the INFO log level (when they log at all).
|
/// DLOG_ASSERT(assertion);
|
||||||
// The verbose logging can also be turned on module-by-module. For instance,
|
/// </pre>
|
||||||
// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
|
///
|
||||||
// will cause:
|
/// which is syntactic sugar for "{,D}LOG_IF(FATAL, assert fails) << assertion;"
|
||||||
// a. VLOG(2) and lower messages to be printed from profile.{h,cc}
|
///
|
||||||
// b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
|
/// There are "verbose level" logging macros. They look like
|
||||||
// c. VLOG(3) and lower messages to be printed from files prefixed with
|
///
|
||||||
// "browser"
|
/// <pre>
|
||||||
// d. VLOG(4) and lower messages to be printed from files under a
|
/// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
|
||||||
// "chromeos" directory.
|
/// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
|
||||||
// e. VLOG(0) and lower messages to be printed from elsewhere
|
/// </pre>
|
||||||
//
|
///
|
||||||
// The wildcarding functionality shown by (c) supports both '*' (match
|
/// These always log at the INFO log level (when they log at all).
|
||||||
// 0 or more characters) and '?' (match any single character)
|
/// The verbose logging can also be turned on module-by-module. For instance,
|
||||||
// wildcards. Any pattern containing a forward or backward slash will
|
/// <pre>
|
||||||
// be tested against the whole pathname and not just the module.
|
/// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
|
||||||
// E.g., "*/foo/bar/*=2" would change the logging level for all code
|
/// </pre>
|
||||||
// in source files under a "foo/bar" directory.
|
/// will cause:
|
||||||
//
|
/// 1. VLOG(2) and lower messages to be printed from profile.{h,cc}
|
||||||
// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
|
/// 2. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
|
||||||
//
|
/// 3. VLOG(3) and lower messages to be printed from files prefixed with
|
||||||
// if (VLOG_IS_ON(2)) {
|
/// "browser"
|
||||||
// // do some logging preparation and logging
|
/// 4. VLOG(4) and lower messages to be printed from files under a
|
||||||
// // that can't be accomplished with just VLOG(2) << ...;
|
/// "chromeos" directory.
|
||||||
// }
|
/// 5. VLOG(0) and lower messages to be printed from elsewhere
|
||||||
//
|
///
|
||||||
// There is also a VLOG_IF "verbose level" condition macro for sample
|
/// The wildcarding functionality shown by (c) supports both '*' (match
|
||||||
// cases, when some extra computation and preparation for logs is not
|
/// 0 or more characters) and '?' (match any single character)
|
||||||
// needed.
|
/// wildcards. Any pattern containing a forward or backward slash will
|
||||||
//
|
/// be tested against the whole pathname and not just the module.
|
||||||
// VLOG_IF(1, (size > 1024))
|
/// E.g., "*/foo/bar/*=2" would change the logging level for all code
|
||||||
// << "I'm printed when size is more than 1024 and when you run the "
|
/// in source files under a "foo/bar" directory.
|
||||||
// "program with --v=1 or more";
|
///
|
||||||
//
|
/// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
|
||||||
// We also override the standard 'assert' to use 'DLOG_ASSERT'.
|
///
|
||||||
//
|
/// <pre>
|
||||||
// Lastly, there is:
|
/// if (VLOG_IS_ON(2)) {
|
||||||
//
|
/// // do some logging preparation and logging
|
||||||
// PLOG(ERROR) << "Couldn't do foo";
|
/// // that can't be accomplished with just VLOG(2) << ...;
|
||||||
// DPLOG(ERROR) << "Couldn't do foo";
|
/// }
|
||||||
// PLOG_IF(ERROR, cond) << "Couldn't do foo";
|
/// </pre>
|
||||||
// DPLOG_IF(ERROR, cond) << "Couldn't do foo";
|
///
|
||||||
// PCHECK(condition) << "Couldn't do foo";
|
/// There is also a VLOG_IF "verbose level" condition macro for sample
|
||||||
// DPCHECK(condition) << "Couldn't do foo";
|
/// cases, when some extra computation and preparation for logs is not
|
||||||
//
|
/// needed.
|
||||||
// which append the last system error to the message in string form (taken from
|
///
|
||||||
// GetLastError() on Windows and errno on POSIX).
|
/// <pre>
|
||||||
//
|
/// VLOG_IF(1, (size > 1024))
|
||||||
// The supported severity levels for macros that allow you to specify one
|
/// << "I'm printed when size is more than 1024 and when you run the "
|
||||||
// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
|
/// "program with --v=1 or more";
|
||||||
//
|
/// </pre>
|
||||||
// Very important: logging a message at the FATAL severity level causes
|
///
|
||||||
// the program to terminate (after the message is logged).
|
/// We also override the standard 'assert' to use 'DLOG_ASSERT'.
|
||||||
//
|
///
|
||||||
// There is the special severity of DFATAL, which logs FATAL in debug mode,
|
/// Lastly, there is:
|
||||||
// ERROR in normal mode.
|
///
|
||||||
//
|
/// <pre>
|
||||||
|
/// PLOG(ERROR) << "Couldn't do foo";
|
||||||
|
/// DPLOG(ERROR) << "Couldn't do foo";
|
||||||
|
/// PLOG_IF(ERROR, cond) << "Couldn't do foo";
|
||||||
|
/// DPLOG_IF(ERROR, cond) << "Couldn't do foo";
|
||||||
|
/// PCHECK(condition) << "Couldn't do foo";
|
||||||
|
/// DPCHECK(condition) << "Couldn't do foo";
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// which append the last system error to the message in string form (taken from
|
||||||
|
/// GetLastError() on Windows and errno on POSIX).
|
||||||
|
///
|
||||||
|
/// The supported severity levels for macros that allow you to specify one
|
||||||
|
/// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
|
||||||
|
///
|
||||||
|
/// Very important: logging a message at the FATAL severity level causes
|
||||||
|
/// the program to terminate (after the message is logged).
|
||||||
|
///
|
||||||
|
/// There is the special severity of DFATAL, which logs FATAL in debug mode,
|
||||||
|
/// ERROR in normal mode.
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
#define CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
||||||
|
@ -38,8 +38,8 @@
|
|||||||
// updated to match.
|
// updated to match.
|
||||||
|
|
||||||
// ALL DISALLOW_xxx MACROS ARE DEPRECATED; DO NOT USE IN NEW CODE.
|
// ALL DISALLOW_xxx MACROS ARE DEPRECATED; DO NOT USE IN NEW CODE.
|
||||||
// Use explicit deletions instead. See the section on copyability/movability in
|
// Use explicit deletions instead. For more information see
|
||||||
// //styleguide/c++/c++-dos-and-donts.md for more information.
|
// https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++-dos-and-donts.md#explicitly-declare-class-copyability_movability
|
||||||
|
|
||||||
// DEPRECATED: See above. Makes a class uncopyable.
|
// DEPRECATED: See above. Makes a class uncopyable.
|
||||||
#define DISALLOW_COPY(TypeName) TypeName(const TypeName&) = delete
|
#define DISALLOW_COPY(TypeName) TypeName(const TypeName&) = delete
|
||||||
|
@ -49,17 +49,21 @@
|
|||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// Used for logging. Always an integer value.
|
///
|
||||||
|
/// Used for logging. Always an integer value.
|
||||||
|
///
|
||||||
typedef cef_platform_thread_id_t PlatformThreadId;
|
typedef cef_platform_thread_id_t PlatformThreadId;
|
||||||
|
|
||||||
// Used for thread checking and debugging.
|
///
|
||||||
// Meant to be as fast as possible.
|
/// Used for thread checking and debugging.
|
||||||
// These are produced by PlatformThread::CurrentRef(), and used to later
|
/// Meant to be as fast as possible.
|
||||||
// check if we are on the same thread or not by using ==. These are safe
|
/// These are produced by PlatformThread::CurrentRef(), and used to later
|
||||||
// to copy between threads, but can't be copied to another process as they
|
/// check if we are on the same thread or not by using ==. These are safe
|
||||||
// have no meaning there. Also, the internal identifier can be re-used
|
/// to copy between threads, but can't be copied to another process as they
|
||||||
// after a thread dies, so a PlatformThreadRef cannot be reliably used
|
/// have no meaning there. Also, the internal identifier can be re-used
|
||||||
// to distinguish a new thread from an old, dead thread.
|
/// after a thread dies, so a PlatformThreadRef cannot be reliably used
|
||||||
|
/// to distinguish a new thread from an old, dead thread.
|
||||||
|
///
|
||||||
class PlatformThreadRef {
|
class PlatformThreadRef {
|
||||||
public:
|
public:
|
||||||
typedef cef_platform_thread_handle_t RefType;
|
typedef cef_platform_thread_handle_t RefType;
|
||||||
@ -76,18 +80,24 @@ class PlatformThreadRef {
|
|||||||
RefType id_;
|
RefType id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A namespace for low-level thread functions.
|
///
|
||||||
// Chromium uses a class with static methods but CEF uses an actual namespace
|
/// A namespace for low-level thread functions.
|
||||||
// to avoid linker problems with the sandbox libaries on Windows.
|
/// Chromium uses a class with static methods but CEF uses an actual namespace
|
||||||
|
/// to avoid linker problems with the sandbox libaries on Windows.
|
||||||
|
///
|
||||||
namespace PlatformThread {
|
namespace PlatformThread {
|
||||||
|
|
||||||
// Gets the current thread id, which may be useful for logging purposes.
|
///
|
||||||
|
/// Gets the current thread id, which may be useful for logging purposes.
|
||||||
|
///
|
||||||
inline PlatformThreadId CurrentId() {
|
inline PlatformThreadId CurrentId() {
|
||||||
return cef_get_current_platform_thread_id();
|
return cef_get_current_platform_thread_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the current thread reference, which can be used to check if
|
///
|
||||||
// we're on the right thread quickly.
|
/// Gets the current thread reference, which can be used to check if
|
||||||
|
/// we're on the right thread quickly.
|
||||||
|
///
|
||||||
inline PlatformThreadRef CurrentRef() {
|
inline PlatformThreadRef CurrentRef() {
|
||||||
return PlatformThreadRef(cef_get_current_platform_thread_handle());
|
return PlatformThreadRef(cef_get_current_platform_thread_handle());
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,11 @@
|
|||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// Helper to transfer ownership of a raw pointer to a std::unique_ptr<T>.
|
///
|
||||||
// Note that std::unique_ptr<T> has very different semantics from
|
/// Helper to transfer ownership of a raw pointer to a std::unique_ptr<T>.
|
||||||
// std::unique_ptr<T[]>: do not use this helper for array allocations.
|
/// Note that std::unique_ptr<T> has very different semantics from
|
||||||
|
/// std::unique_ptr<T[]>: do not use this helper for array allocations.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<T> WrapUnique(T* ptr) {
|
std::unique_ptr<T> WrapUnique(T* ptr) {
|
||||||
return std::unique_ptr<T>(ptr);
|
return std::unique_ptr<T>(ptr);
|
||||||
|
@ -290,52 +290,26 @@ class ScopedAllowCrossThreadRefCountAccess final {
|
|||||||
using ScopedAllowCrossThreadRefCountAccess =
|
using ScopedAllowCrossThreadRefCountAccess =
|
||||||
cef_subtle::ScopedAllowCrossThreadRefCountAccess;
|
cef_subtle::ScopedAllowCrossThreadRefCountAccess;
|
||||||
|
|
||||||
//
|
///
|
||||||
// A base class for reference counted classes. Otherwise, known as a cheap
|
/// The reference count starts from zero by default, and we intended to migrate
|
||||||
// knock-off of WebKit's RefCounted<T> class. To use this, just extend your
|
/// to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to
|
||||||
// class from it like so:
|
/// the ref counted class to opt-in.
|
||||||
//
|
///
|
||||||
// class MyFoo : public base::RefCounted<MyFoo> {
|
/// If an object has start-from-one ref count, the first scoped_refptr need to
|
||||||
// ...
|
/// be created by base::AdoptRef() or base::MakeRefCounted(). We can use
|
||||||
// private:
|
/// base::MakeRefCounted() to create create both type of ref counted object.
|
||||||
// friend class base::RefCounted<MyFoo>;
|
///
|
||||||
// ~MyFoo();
|
/// The motivations to use start-from-one ref count are:
|
||||||
// };
|
/// - Start-from-one ref count doesn't need the ref count increment for the
|
||||||
//
|
/// first reference.
|
||||||
// Usage Notes:
|
/// - It can detect an invalid object acquisition for a being-deleted object
|
||||||
// 1. You should always make your destructor non-public, to avoid any code
|
/// that has zero ref count. That tends to happen on custom deleter that
|
||||||
// deleting the object accidentally while there are references to it.
|
/// delays the deletion.
|
||||||
// 2. You should always make the ref-counted base class a friend of your class,
|
/// TODO(tzik): Implement invalid acquisition detection.
|
||||||
// so that it can access the destructor.
|
/// - Behavior parity to Blink's WTF::RefCounted, whose count starts from one.
|
||||||
//
|
/// And start-from-one ref count is a step to merge WTF::RefCounted into
|
||||||
// The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs
|
/// base::RefCounted.
|
||||||
// to trap unsafe cross thread usage. A subclass instance of RefCounted can be
|
///
|
||||||
// passed to another execution thread only when its ref count is 1. If the ref
|
|
||||||
// count is more than 1, the RefCounted class verifies the ref updates are made
|
|
||||||
// on the same execution thread as the previous ones. The subclass can also
|
|
||||||
// manually call IsOnValidThread to trap other non-thread-safe accesses; see
|
|
||||||
// the documentation for that method.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// The reference count starts from zero by default, and we intended to migrate
|
|
||||||
// to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to
|
|
||||||
// the ref counted class to opt-in.
|
|
||||||
//
|
|
||||||
// If an object has start-from-one ref count, the first scoped_refptr need to be
|
|
||||||
// created by base::AdoptRef() or base::MakeRefCounted(). We can use
|
|
||||||
// base::MakeRefCounted() to create create both type of ref counted object.
|
|
||||||
//
|
|
||||||
// The motivations to use start-from-one ref count are:
|
|
||||||
// - Start-from-one ref count doesn't need the ref count increment for the
|
|
||||||
// first reference.
|
|
||||||
// - It can detect an invalid object acquisition for a being-deleted object
|
|
||||||
// that has zero ref count. That tends to happen on custom deleter that
|
|
||||||
// delays the deletion.
|
|
||||||
// TODO(tzik): Implement invalid acquisition detection.
|
|
||||||
// - Behavior parity to Blink's WTF::RefCounted, whose count starts from one.
|
|
||||||
// And start-from-one ref count is a step to merge WTF::RefCounted into
|
|
||||||
// base::RefCounted.
|
|
||||||
//
|
|
||||||
#define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \
|
#define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \
|
||||||
static constexpr ::base::cef_subtle::StartRefCountFromOneTag \
|
static constexpr ::base::cef_subtle::StartRefCountFromOneTag \
|
||||||
kRefCountPreference = ::base::cef_subtle::kStartRefCountFromOneTag
|
kRefCountPreference = ::base::cef_subtle::kStartRefCountFromOneTag
|
||||||
@ -343,6 +317,10 @@ using ScopedAllowCrossThreadRefCountAccess =
|
|||||||
template <class T, typename Traits>
|
template <class T, typename Traits>
|
||||||
class RefCounted;
|
class RefCounted;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Default traits for RefCounted<T>. Deletes the object when its ref count
|
||||||
|
/// reaches 0. Overload to delete it on a different thread etc.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct DefaultRefCountedTraits {
|
struct DefaultRefCountedTraits {
|
||||||
static void Destruct(const T* x) {
|
static void Destruct(const T* x) {
|
||||||
@ -350,6 +328,34 @@ struct DefaultRefCountedTraits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// A base class for reference counted classes. Otherwise, known as a cheap
|
||||||
|
/// knock-off of WebKit's RefCounted<T> class. To use this, just extend your
|
||||||
|
/// class from it like so:
|
||||||
|
///
|
||||||
|
/// <pre>
|
||||||
|
/// class MyFoo : public base::RefCounted<MyFoo> {
|
||||||
|
/// ...
|
||||||
|
/// private:
|
||||||
|
/// friend class base::RefCounted<MyFoo>;
|
||||||
|
/// ~MyFoo();
|
||||||
|
/// };
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// Usage Notes:
|
||||||
|
/// 1. You should always make your destructor non-public, to avoid any code
|
||||||
|
/// deleting the object accidentally while there are references to it.
|
||||||
|
/// 2. You should always make the ref-counted base class a friend of your class,
|
||||||
|
/// so that it can access the destructor.
|
||||||
|
///
|
||||||
|
/// The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs
|
||||||
|
/// to trap unsafe cross thread usage. A subclass instance of RefCounted can be
|
||||||
|
/// passed to another execution thread only when its ref count is 1. If the ref
|
||||||
|
/// count is more than 1, the RefCounted class verifies the ref updates are made
|
||||||
|
/// on the same execution thread as the previous ones. The subclass can also
|
||||||
|
/// manually call IsOnValidThread to trap other non-thread-safe accesses; see
|
||||||
|
/// the documentation for that method.
|
||||||
|
///
|
||||||
template <class T, typename Traits = DefaultRefCountedTraits<T>>
|
template <class T, typename Traits = DefaultRefCountedTraits<T>>
|
||||||
class RefCounted : public cef_subtle::RefCountedBase {
|
class RefCounted : public cef_subtle::RefCountedBase {
|
||||||
public:
|
public:
|
||||||
@ -389,8 +395,10 @@ class RefCounted : public cef_subtle::RefCountedBase {
|
|||||||
template <class T, typename Traits>
|
template <class T, typename Traits>
|
||||||
class RefCountedThreadSafe;
|
class RefCountedThreadSafe;
|
||||||
|
|
||||||
// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
|
///
|
||||||
// count reaches 0. Overload to delete it on a different thread etc.
|
/// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
|
||||||
|
/// count reaches 0. Overload to delete it on a different thread etc.
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct DefaultRefCountedThreadSafeTraits {
|
struct DefaultRefCountedThreadSafeTraits {
|
||||||
static void Destruct(const T* x) {
|
static void Destruct(const T* x) {
|
||||||
@ -402,21 +410,26 @@ struct DefaultRefCountedThreadSafeTraits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
///
|
||||||
// A thread-safe variant of RefCounted<T>
|
/// A thread-safe variant of RefCounted<T>
|
||||||
//
|
///
|
||||||
// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
|
/// <pre>
|
||||||
// ...
|
/// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
|
||||||
// };
|
/// ...
|
||||||
//
|
/// };
|
||||||
// If you're using the default trait, then you should add compile time
|
/// </pre>
|
||||||
// asserts that no one else is deleting your object. i.e.
|
///
|
||||||
// private:
|
/// If you're using the default trait, then you should add compile time
|
||||||
// friend class base::RefCountedThreadSafe<MyFoo>;
|
/// asserts that no one else is deleting your object. i.e.
|
||||||
// ~MyFoo();
|
/// <pre>
|
||||||
//
|
/// private:
|
||||||
// We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe
|
/// friend class base::RefCountedThreadSafe<MyFoo>;
|
||||||
// too. See the comment above the RefCounted definition for details.
|
/// ~MyFoo();
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe
|
||||||
|
/// too. See the comment above the RefCounted definition for details.
|
||||||
|
///
|
||||||
template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T>>
|
template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T>>
|
||||||
class RefCountedThreadSafe : public cef_subtle::RefCountedThreadSafeBase {
|
class RefCountedThreadSafe : public cef_subtle::RefCountedThreadSafeBase {
|
||||||
public:
|
public:
|
||||||
@ -457,10 +470,10 @@ class RefCountedThreadSafe : public cef_subtle::RefCountedThreadSafeBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
///
|
||||||
// A thread-safe wrapper for some piece of data so we can place other
|
/// A thread-safe wrapper for some piece of data so we can place other
|
||||||
// things in scoped_refptrs<>.
|
/// things in scoped_refptrs<>.
|
||||||
//
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class RefCountedData
|
class RefCountedData
|
||||||
: public base::RefCountedThreadSafe<base::RefCountedData<T>> {
|
: public base::RefCountedThreadSafe<base::RefCountedData<T>> {
|
||||||
|
@ -142,68 +142,76 @@ scoped_refptr<T> WrapRefCounted(T* t) {
|
|||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
||||||
//
|
///
|
||||||
// A smart pointer class for reference counted objects. Use this class instead
|
/// A smart pointer class for reference counted objects. Use this class instead
|
||||||
// of calling AddRef and Release manually on a reference counted object to
|
/// of calling AddRef and Release manually on a reference counted object to
|
||||||
// avoid common memory leaks caused by forgetting to Release an object
|
/// avoid common memory leaks caused by forgetting to Release an object
|
||||||
// reference. Sample usage:
|
/// reference. Sample usage:
|
||||||
//
|
///
|
||||||
// class MyFoo : public RefCounted<MyFoo> {
|
/// <pre>
|
||||||
// ...
|
/// class MyFoo : public RefCounted<MyFoo> {
|
||||||
// private:
|
/// ...
|
||||||
// friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>.
|
/// private:
|
||||||
// ~MyFoo(); // Destructor must be private/protected.
|
/// friend class RefCounted<MyFoo>; // Allow destruction by RefCounted<>.
|
||||||
// };
|
/// ~MyFoo(); // Destructor must be
|
||||||
//
|
/// private/protected.
|
||||||
// void some_function() {
|
/// };
|
||||||
// scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
|
///
|
||||||
// foo->Method(param);
|
/// void some_function() {
|
||||||
// // |foo| is released when this function returns
|
/// scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
|
||||||
// }
|
/// foo->Method(param);
|
||||||
//
|
/// // |foo| is released when this function returns
|
||||||
// void some_other_function() {
|
/// }
|
||||||
// scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
|
///
|
||||||
// ...
|
/// void some_other_function() {
|
||||||
// foo.reset(); // explicitly releases |foo|
|
/// scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
|
||||||
// ...
|
/// ...
|
||||||
// if (foo)
|
/// foo.reset(); // explicitly releases |foo|
|
||||||
// foo->Method(param);
|
/// ...
|
||||||
// }
|
/// if (foo)
|
||||||
//
|
/// foo->Method(param);
|
||||||
// The above examples show how scoped_refptr<T> acts like a pointer to T.
|
/// }
|
||||||
// Given two scoped_refptr<T> classes, it is also possible to exchange
|
/// </pre>
|
||||||
// references between the two objects, like so:
|
///
|
||||||
//
|
/// The above examples show how scoped_refptr<T> acts like a pointer to T.
|
||||||
// {
|
/// Given two scoped_refptr<T> classes, it is also possible to exchange
|
||||||
// scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
|
/// references between the two objects, like so:
|
||||||
// scoped_refptr<MyFoo> b;
|
///
|
||||||
//
|
/// <pre>
|
||||||
// b.swap(a);
|
/// {
|
||||||
// // now, |b| references the MyFoo object, and |a| references nullptr.
|
/// scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
|
||||||
// }
|
/// scoped_refptr<MyFoo> b;
|
||||||
//
|
///
|
||||||
// To make both |a| and |b| in the above example reference the same MyFoo
|
/// b.swap(a);
|
||||||
// object, simply use the assignment operator:
|
/// // now, |b| references the MyFoo object, and |a| references nullptr.
|
||||||
//
|
/// }
|
||||||
// {
|
/// </pre>
|
||||||
// scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
|
///
|
||||||
// scoped_refptr<MyFoo> b;
|
/// To make both |a| and |b| in the above example reference the same MyFoo
|
||||||
//
|
/// object, simply use the assignment operator:
|
||||||
// b = a;
|
///
|
||||||
// // now, |a| and |b| each own a reference to the same MyFoo object.
|
/// <pre>
|
||||||
// }
|
/// {
|
||||||
//
|
/// scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
|
||||||
// Also see Chromium's ownership and calling conventions:
|
/// scoped_refptr<MyFoo> b;
|
||||||
// https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
|
///
|
||||||
// Specifically:
|
/// b = a;
|
||||||
// If the function (at least sometimes) takes a ref on a refcounted object,
|
/// // now, |a| and |b| each own a reference to the same MyFoo object.
|
||||||
// declare the param as scoped_refptr<T>. The caller can decide whether it
|
/// }
|
||||||
// wishes to transfer ownership (by calling std::move(t) when passing t) or
|
/// </pre>
|
||||||
// retain its ref (by simply passing t directly).
|
///
|
||||||
// In other words, use scoped_refptr like you would a std::unique_ptr except
|
/// Also see Chromium's ownership and calling conventions:
|
||||||
// in the odd case where it's required to hold on to a ref while handing one
|
/// https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
|
||||||
// to another component (if a component merely needs to use t on the stack
|
/// Specifically:
|
||||||
// without keeping a ref: pass t as a raw T*).
|
/// If the function (at least sometimes) takes a ref on a refcounted object,
|
||||||
|
/// declare the param as scoped_refptr<T>. The caller can decide whether it
|
||||||
|
/// wishes to transfer ownership (by calling std::move(t) when passing t) or
|
||||||
|
/// retain its ref (by simply passing t directly).
|
||||||
|
/// In other words, use scoped_refptr like you would a std::unique_ptr except
|
||||||
|
/// in the odd case where it's required to hold on to a ref while handing one
|
||||||
|
/// to another component (if a component merely needs to use t on the stack
|
||||||
|
/// without keeping a ref: pass t as a raw T*).
|
||||||
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
class TRIVIAL_ABI scoped_refptr {
|
class TRIVIAL_ABI scoped_refptr {
|
||||||
public:
|
public:
|
||||||
|
@ -28,40 +28,6 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains ownership
|
|
||||||
// of a reference to any type that is maintained by Retain and Release methods.
|
|
||||||
//
|
|
||||||
// The Traits structure must provide the Retain and Release methods for type T.
|
|
||||||
// A default ScopedTypeRefTraits is used but not defined, and should be defined
|
|
||||||
// for each type to use this interface. For example, an appropriate definition
|
|
||||||
// of ScopedTypeRefTraits for CGLContextObj would be:
|
|
||||||
//
|
|
||||||
// template<>
|
|
||||||
// struct ScopedTypeRefTraits<CGLContextObj> {
|
|
||||||
// static CGLContextObj InvalidValue() { return nullptr; }
|
|
||||||
// static CGLContextObj Retain(CGLContextObj object) {
|
|
||||||
// CGLContextRetain(object);
|
|
||||||
// return object;
|
|
||||||
// }
|
|
||||||
// static void Release(CGLContextObj object) { CGLContextRelease(object); }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// For the many types that have pass-by-pointer create functions, the function
|
|
||||||
// InitializeInto() is provided to allow direct initialization and assumption
|
|
||||||
// of ownership of the object. For example, continuing to use the above
|
|
||||||
// CGLContextObj specialization:
|
|
||||||
//
|
|
||||||
// base::ScopedTypeRef<CGLContextObj> context;
|
|
||||||
// CGLCreateContext(pixel_format, share_group, context.InitializeInto());
|
|
||||||
//
|
|
||||||
// For initialization with an existing object, the caller may specify whether
|
|
||||||
// the ScopedTypeRef<> being initialized is assuming the caller's existing
|
|
||||||
// ownership of the object (and should not call Retain in initialization) or if
|
|
||||||
// it should not assume this ownership and must create its own (by calling
|
|
||||||
// Retain in initialization). This behavior is based on the |policy| parameter,
|
|
||||||
// with |ASSUME| for the former and |RETAIN| for the latter. The default policy
|
|
||||||
// is to |ASSUME|.
|
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
|
#define CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -82,6 +48,46 @@ namespace base {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct ScopedTypeRefTraits;
|
struct ScopedTypeRefTraits;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains
|
||||||
|
/// ownership of a reference to any type that is maintained by Retain and
|
||||||
|
/// Release methods.
|
||||||
|
///
|
||||||
|
/// The Traits structure must provide the Retain and Release methods for type T.
|
||||||
|
/// A default ScopedTypeRefTraits is used but not defined, and should be defined
|
||||||
|
/// for each type to use this interface. For example, an appropriate definition
|
||||||
|
/// of ScopedTypeRefTraits for CGLContextObj would be:
|
||||||
|
///
|
||||||
|
/// <pre>
|
||||||
|
/// template<>
|
||||||
|
/// struct ScopedTypeRefTraits<CGLContextObj> {
|
||||||
|
/// static CGLContextObj InvalidValue() { return nullptr; }
|
||||||
|
/// static CGLContextObj Retain(CGLContextObj object) {
|
||||||
|
/// CGLContextRetain(object);
|
||||||
|
/// return object;
|
||||||
|
/// }
|
||||||
|
/// static void Release(CGLContextObj object) { CGLContextRelease(object); }
|
||||||
|
/// };
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// For the many types that have pass-by-pointer create functions, the function
|
||||||
|
/// InitializeInto() is provided to allow direct initialization and assumption
|
||||||
|
/// of ownership of the object. For example, continuing to use the above
|
||||||
|
/// CGLContextObj specialization:
|
||||||
|
///
|
||||||
|
/// <pre>
|
||||||
|
/// base::ScopedTypeRef<CGLContextObj> context;
|
||||||
|
/// CGLCreateContext(pixel_format, share_group, context.InitializeInto());
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// For initialization with an existing object, the caller may specify whether
|
||||||
|
/// the ScopedTypeRef<> being initialized is assuming the caller's existing
|
||||||
|
/// ownership of the object (and should not call Retain in initialization) or if
|
||||||
|
/// it should not assume this ownership and must create its own (by calling
|
||||||
|
/// Retain in initialization). This behavior is based on the |policy| parameter,
|
||||||
|
/// with |ASSUME| for the former and |RETAIN| for the latter. The default policy
|
||||||
|
/// is to |ASSUME|.
|
||||||
|
///
|
||||||
template <typename T, typename Traits = ScopedTypeRefTraits<T>>
|
template <typename T, typename Traits = ScopedTypeRefTraits<T>>
|
||||||
class ScopedTypeRef {
|
class ScopedTypeRef {
|
||||||
public:
|
public:
|
||||||
|
@ -43,10 +43,12 @@
|
|||||||
#include "include/base/cef_logging.h"
|
#include "include/base/cef_logging.h"
|
||||||
#include "include/base/internal/cef_thread_checker_impl.h"
|
#include "include/base/internal/cef_thread_checker_impl.h"
|
||||||
|
|
||||||
// Apart from debug builds, we also enable the thread checker in
|
///
|
||||||
// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
|
/// Apart from debug builds, we also enable the thread checker in
|
||||||
// with this define will get the same level of thread checking as
|
/// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
|
||||||
// debug bots.
|
/// with this define will get the same level of thread checking as
|
||||||
|
/// debug bots.
|
||||||
|
///
|
||||||
#if DCHECK_IS_ON()
|
#if DCHECK_IS_ON()
|
||||||
#define ENABLE_THREAD_CHECKER 1
|
#define ENABLE_THREAD_CHECKER 1
|
||||||
#else
|
#else
|
||||||
@ -57,10 +59,12 @@ namespace base {
|
|||||||
|
|
||||||
namespace cef_internal {
|
namespace cef_internal {
|
||||||
|
|
||||||
// Do nothing implementation, for use in release mode.
|
///
|
||||||
//
|
/// Do nothing implementation, for use in release mode.
|
||||||
// Note: You should almost always use the ThreadChecker class to get the
|
///
|
||||||
// right version for your build configuration.
|
/// Note: You should almost always use the ThreadChecker class to get the
|
||||||
|
/// right version for your build configuration.
|
||||||
|
///
|
||||||
class ThreadCheckerDoNothing {
|
class ThreadCheckerDoNothing {
|
||||||
public:
|
public:
|
||||||
bool CalledOnValidThread() const { return true; }
|
bool CalledOnValidThread() const { return true; }
|
||||||
@ -70,37 +74,42 @@ class ThreadCheckerDoNothing {
|
|||||||
|
|
||||||
} // namespace cef_internal
|
} // namespace cef_internal
|
||||||
|
|
||||||
// ThreadChecker is a helper class used to help verify that some methods of a
|
///
|
||||||
// class are called from the same thread. It provides identical functionality to
|
/// ThreadChecker is a helper class used to help verify that some methods of a
|
||||||
// base::NonThreadSafe, but it is meant to be held as a member variable, rather
|
/// class are called from the same thread. It provides identical functionality
|
||||||
// than inherited from base::NonThreadSafe.
|
/// to base::NonThreadSafe, but it is meant to be held as a member variable,
|
||||||
//
|
/// rather than inherited from base::NonThreadSafe.
|
||||||
// While inheriting from base::NonThreadSafe may give a clear indication about
|
///
|
||||||
// the thread-safety of a class, it may also lead to violations of the style
|
/// While inheriting from base::NonThreadSafe may give a clear indication about
|
||||||
// guide with regard to multiple inheritance. The choice between having a
|
/// the thread-safety of a class, it may also lead to violations of the style
|
||||||
// ThreadChecker member and inheriting from base::NonThreadSafe should be based
|
/// guide with regard to multiple inheritance. The choice between having a
|
||||||
// on whether:
|
/// ThreadChecker member and inheriting from base::NonThreadSafe should be based
|
||||||
// - Derived classes need to know the thread they belong to, as opposed to
|
/// on whether:
|
||||||
// having that functionality fully encapsulated in the base class.
|
/// - Derived classes need to know the thread they belong to, as opposed to
|
||||||
// - Derived classes should be able to reassign the base class to another
|
/// having that functionality fully encapsulated in the base class.
|
||||||
// thread, via DetachFromThread.
|
/// - Derived classes should be able to reassign the base class to another
|
||||||
//
|
/// thread, via DetachFromThread.
|
||||||
// If neither of these are true, then having a ThreadChecker member and calling
|
///
|
||||||
// CalledOnValidThread is the preferable solution.
|
/// If neither of these are true, then having a ThreadChecker member and calling
|
||||||
//
|
/// CalledOnValidThread is the preferable solution.
|
||||||
// Example:
|
///
|
||||||
// class MyClass {
|
/// Example:
|
||||||
// public:
|
///
|
||||||
// void Foo() {
|
/// <pre>
|
||||||
// DCHECK(thread_checker_.CalledOnValidThread());
|
/// class MyClass {
|
||||||
// ... (do stuff) ...
|
/// public:
|
||||||
// }
|
/// void Foo() {
|
||||||
//
|
/// DCHECK(thread_checker_.CalledOnValidThread());
|
||||||
// private:
|
/// ... (do stuff) ...
|
||||||
// ThreadChecker thread_checker_;
|
/// }
|
||||||
// }
|
///
|
||||||
//
|
/// private:
|
||||||
// In Release mode, CalledOnValidThread will always return true.
|
/// ThreadChecker thread_checker_;
|
||||||
|
/// }
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// In Release mode, CalledOnValidThread will always return true.
|
||||||
|
///
|
||||||
#if ENABLE_THREAD_CHECKER
|
#if ENABLE_THREAD_CHECKER
|
||||||
class ThreadChecker : public cef_internal::ThreadCheckerImpl {};
|
class ThreadChecker : public cef_internal::ThreadCheckerImpl {};
|
||||||
#else
|
#else
|
||||||
|
@ -29,111 +29,133 @@
|
|||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
///
|
///
|
||||||
// Trace events are for tracking application performance and resource usage.
|
/// \file
|
||||||
// Macros are provided to track:
|
/// Trace events are for tracking application performance and resource usage.
|
||||||
// Begin and end of function calls
|
/// Macros are provided to track:
|
||||||
// Counters
|
/// Begin and end of function calls
|
||||||
//
|
/// Counters
|
||||||
// Events are issued against categories. Whereas LOG's categories are statically
|
///
|
||||||
// defined, TRACE categories are created implicitly with a string. For example:
|
/// Events are issued against categories. Whereas LOG's categories are
|
||||||
// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
|
/// statically defined, TRACE categories are created implicitly with a string.
|
||||||
//
|
/// For example: <pre>
|
||||||
// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
|
/// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
|
||||||
// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
|
/// </pre>
|
||||||
// doSomethingCostly()
|
///
|
||||||
// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
|
/// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
|
||||||
// Note: Our tools can't always determine the correct BEGIN/END pairs unless
|
/// <pre>
|
||||||
// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
|
/// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
|
||||||
// need them to be in separate scopes.
|
/// doSomethingCostly()
|
||||||
//
|
/// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
|
||||||
// A common use case is to trace entire function scopes. This issues a trace
|
/// </pre>
|
||||||
// BEGIN and END automatically:
|
/// Note: Our tools can't always determine the correct BEGIN/END pairs unless
|
||||||
// void doSomethingCostly() {
|
/// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
|
||||||
// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
|
/// need them to be in separate scopes.
|
||||||
// ...
|
///
|
||||||
// }
|
/// A common use case is to trace entire function scopes. This issues a trace
|
||||||
//
|
/// BEGIN and END automatically:
|
||||||
// Additional parameters can be associated with an event:
|
/// <pre>
|
||||||
// void doSomethingCostly2(int howMuch) {
|
/// void doSomethingCostly() {
|
||||||
// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
|
/// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
|
||||||
// "howMuch", howMuch);
|
/// ...
|
||||||
// ...
|
/// }
|
||||||
// }
|
/// </pre>
|
||||||
//
|
///
|
||||||
// The trace system will automatically add to this information the current
|
/// Additional parameters can be associated with an event:
|
||||||
// process id, thread id, and a timestamp in microseconds.
|
/// <pre>
|
||||||
//
|
/// void doSomethingCostly2(int howMuch) {
|
||||||
// To trace an asynchronous procedure such as an IPC send/receive, use
|
/// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
|
||||||
// ASYNC_BEGIN and ASYNC_END:
|
/// "howMuch", howMuch);
|
||||||
// [single threaded sender code]
|
/// ...
|
||||||
// static int send_count = 0;
|
/// }
|
||||||
// ++send_count;
|
/// </pre>
|
||||||
// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
|
///
|
||||||
// Send(new MyMessage(send_count));
|
/// The trace system will automatically add to this information the current
|
||||||
// [receive code]
|
/// process id, thread id, and a timestamp in microseconds.
|
||||||
// void OnMyMessage(send_count) {
|
///
|
||||||
// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
|
/// To trace an asynchronous procedure such as an IPC send/receive, use
|
||||||
// }
|
/// ASYNC_BEGIN and ASYNC_END:
|
||||||
// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
|
/// <pre>
|
||||||
// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
|
/// [single threaded sender code]
|
||||||
// Pointers can be used for the ID parameter, and they will be mangled
|
/// static int send_count = 0;
|
||||||
// internally so that the same pointer on two different processes will not
|
/// ++send_count;
|
||||||
// match. For example:
|
/// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
|
||||||
// class MyTracedClass {
|
/// Send(new MyMessage(send_count));
|
||||||
// public:
|
/// [receive code]
|
||||||
// MyTracedClass() {
|
/// void OnMyMessage(send_count) {
|
||||||
// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
|
/// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
|
||||||
// }
|
/// }
|
||||||
// ~MyTracedClass() {
|
/// </pre>
|
||||||
// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
|
/// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
|
||||||
// }
|
/// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
|
||||||
// }
|
/// Pointers can be used for the ID parameter, and they will be mangled
|
||||||
//
|
/// internally so that the same pointer on two different processes will not
|
||||||
// The trace event also supports counters, which is a way to track a quantity
|
/// match. For example:
|
||||||
// as it varies over time. Counters are created with the following macro:
|
/// <pre>
|
||||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
|
/// class MyTracedClass {
|
||||||
//
|
/// public:
|
||||||
// Counters are process-specific. The macro itself can be issued from any
|
/// MyTracedClass() {
|
||||||
// thread, however.
|
/// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
|
||||||
//
|
/// }
|
||||||
// Sometimes, you want to track two counters at once. You can do this with two
|
/// ~MyTracedClass() {
|
||||||
// counter macros:
|
/// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
|
||||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
|
/// }
|
||||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
|
/// }
|
||||||
// Or you can do it with a combined macro:
|
/// </pre>
|
||||||
// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
|
///
|
||||||
// "bytesPinned", g_myCounterValue[0],
|
/// The trace event also supports counters, which is a way to track a quantity
|
||||||
// "bytesAllocated", g_myCounterValue[1]);
|
/// as it varies over time. Counters are created with the following macro:
|
||||||
// This indicates to the tracing UI that these counters should be displayed
|
/// <pre>
|
||||||
// in a single graph, as a summed area chart.
|
/// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
|
||||||
//
|
/// </pre>
|
||||||
// Since counters are in a global namespace, you may want to disembiguate with a
|
///
|
||||||
// unique ID, by using the TRACE_COUNTER_ID* variations.
|
/// Counters are process-specific. The macro itself can be issued from any
|
||||||
//
|
/// thread, however.
|
||||||
// By default, trace collection is compiled in, but turned off at runtime.
|
///
|
||||||
// Collecting trace data is the responsibility of the embedding application. In
|
/// Sometimes, you want to track two counters at once. You can do this with two
|
||||||
// CEF's case, calling BeginTracing will turn on tracing on all active
|
/// counter macros:
|
||||||
// processes.
|
/// <pre>
|
||||||
//
|
/// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
|
||||||
//
|
/// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
|
||||||
// Memory scoping note:
|
/// </pre>
|
||||||
// Tracing copies the pointers, not the string content, of the strings passed
|
/// Or you can do it with a combined macro:
|
||||||
// in for category, name, and arg_names. Thus, the following code will cause
|
/// <pre>
|
||||||
// problems:
|
/// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
|
||||||
// char* str = strdup("impprtantName");
|
/// "bytesPinned", g_myCounterValue[0],
|
||||||
// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
|
/// "bytesAllocated", g_myCounterValue[1]);
|
||||||
// free(str); // Trace system now has dangling pointer
|
/// </pre>
|
||||||
//
|
/// This indicates to the tracing UI that these counters should be displayed
|
||||||
// To avoid this issue with the |name| and |arg_name| parameters, use the
|
/// in a single graph, as a summed area chart.
|
||||||
// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime
|
///
|
||||||
// overhead.
|
/// Since counters are in a global namespace, you may want to disembiguate with
|
||||||
// Notes: The category must always be in a long-lived char* (i.e. static const).
|
/// a unique ID, by using the TRACE_COUNTER_ID* variations.
|
||||||
// The |arg_values|, when used, are always deep copied with the _COPY
|
///
|
||||||
// macros.
|
/// By default, trace collection is compiled in, but turned off at runtime.
|
||||||
//
|
/// Collecting trace data is the responsibility of the embedding application. In
|
||||||
//
|
/// CEF's case, calling BeginTracing will turn on tracing on all active
|
||||||
// Thread Safety:
|
/// processes.
|
||||||
// All macros are thread safe and can be used from any process.
|
///
|
||||||
|
///
|
||||||
|
/// Memory scoping note:
|
||||||
|
/// Tracing copies the pointers, not the string content, of the strings passed
|
||||||
|
/// in for category, name, and arg_names. Thus, the following code will cause
|
||||||
|
/// problems:
|
||||||
|
/// <pre>
|
||||||
|
/// char* str = strdup("impprtantName");
|
||||||
|
/// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
|
||||||
|
/// free(str); // Trace system now has dangling pointer
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
/// To avoid this issue with the |name| and |arg_name| parameters, use the
|
||||||
|
/// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime
|
||||||
|
/// overhead.
|
||||||
|
///
|
||||||
|
/// Notes: The category must always be in a long-lived char* (i.e. static
|
||||||
|
/// const). The |arg_values|, when used, are always deep copied with
|
||||||
|
/// the _COPY macros.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Thread Safety:
|
||||||
|
/// All macros are thread safe and can be used from any process.
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
|
||||||
@ -141,7 +163,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(USING_CHROMIUM_INCLUDES)
|
#if defined(USING_CHROMIUM_INCLUDES)
|
||||||
// When building CEF include the Chromium header directly.
|
/// When building CEF include the Chromium header directly.
|
||||||
#include "base/trace_event/trace_event.h"
|
#include "base/trace_event/trace_event.h"
|
||||||
#else // !USING_CHROMIUM_INCLUDES
|
#else // !USING_CHROMIUM_INCLUDES
|
||||||
// The following is substantially similar to the Chromium implementation.
|
// The following is substantially similar to the Chromium implementation.
|
||||||
@ -150,11 +172,13 @@
|
|||||||
|
|
||||||
#include "include/internal/cef_trace_event_internal.h"
|
#include "include/internal/cef_trace_event_internal.h"
|
||||||
|
|
||||||
// Records a pair of begin and end events called "name" for the current
|
///
|
||||||
// scope, with 0, 1 or 2 associated arguments. If the category is not
|
/// Records a pair of begin and end events called "name" for the current
|
||||||
// enabled, then this does nothing.
|
/// scope, with 0, 1 or 2 associated arguments. If the category is not
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// enabled, then this does nothing.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_EVENT0(category, name) \
|
#define TRACE_EVENT0(category, name) \
|
||||||
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \
|
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \
|
||||||
CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
|
CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
|
||||||
@ -179,11 +203,13 @@
|
|||||||
cef_trace_event::CefTraceEndOnScopeClose CEF_INTERNAL_TRACE_EVENT_UID( \
|
cef_trace_event::CefTraceEndOnScopeClose CEF_INTERNAL_TRACE_EVENT_UID( \
|
||||||
profileScope)(category, name)
|
profileScope)(category, name)
|
||||||
|
|
||||||
// Records a single event called "name" immediately, with 0, 1 or 2
|
///
|
||||||
// associated arguments. If the category is not enabled, then this
|
/// Records a single event called "name" immediately, with 0, 1 or 2
|
||||||
// does nothing.
|
/// associated arguments. If the category is not enabled, then this
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// does nothing.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_INSTANT0(category, name) \
|
#define TRACE_EVENT_INSTANT0(category, name) \
|
||||||
cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false)
|
cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false)
|
||||||
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||||
@ -201,11 +227,13 @@
|
|||||||
cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
|
cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
|
||||||
arg2_val, true)
|
arg2_val, true)
|
||||||
|
|
||||||
// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
|
///
|
||||||
// associated arguments. If the category is not enabled, then this
|
/// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
|
||||||
// does nothing.
|
/// associated arguments. If the category is not enabled, then this
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// does nothing.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_BEGIN0(category, name) \
|
#define TRACE_EVENT_BEGIN0(category, name) \
|
||||||
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false)
|
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false)
|
||||||
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
|
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
|
||||||
@ -223,10 +251,12 @@
|
|||||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
|
cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
|
||||||
arg2_val, true)
|
arg2_val, true)
|
||||||
|
|
||||||
// Records a single END event for "name" immediately. If the category
|
///
|
||||||
// is not enabled, then this does nothing.
|
/// Records a single END event for "name" immediately. If the category
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// is not enabled, then this does nothing.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_END0(category, name) \
|
#define TRACE_EVENT_END0(category, name) \
|
||||||
cef_trace_event_end(category, name, NULL, 0, NULL, 0, false)
|
cef_trace_event_end(category, name, NULL, 0, NULL, 0, false)
|
||||||
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
|
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
|
||||||
@ -244,20 +274,24 @@
|
|||||||
cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
|
cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
|
||||||
arg2_val, true)
|
arg2_val, true)
|
||||||
|
|
||||||
// Records the value of a counter called "name" immediately. Value
|
///
|
||||||
// must be representable as a 32 bit integer.
|
/// Records the value of a counter called "name" immediately. Value
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// must be representable as a 32 bit integer.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_COUNTER1(category, name, value) \
|
#define TRACE_COUNTER1(category, name, value) \
|
||||||
cef_trace_counter(category, name, NULL, value, NULL, 0, false)
|
cef_trace_counter(category, name, NULL, value, NULL, 0, false)
|
||||||
#define TRACE_COPY_COUNTER1(category, name, value) \
|
#define TRACE_COPY_COUNTER1(category, name, value) \
|
||||||
cef_trace_counter(category, name, NULL, value, NULL, 0, true)
|
cef_trace_counter(category, name, NULL, value, NULL, 0, true)
|
||||||
|
|
||||||
// Records the values of a multi-parted counter called "name" immediately.
|
///
|
||||||
// The UI will treat value1 and value2 as parts of a whole, displaying their
|
/// Records the values of a multi-parted counter called "name" immediately.
|
||||||
// values as a stacked-bar chart.
|
/// The UI will treat value1 and value2 as parts of a whole, displaying their
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// values as a stacked-bar chart.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
|
/// literals). They may not include " chars.
|
||||||
|
///
|
||||||
#define TRACE_COUNTER2(category, name, value1_name, value1_val, value2_name, \
|
#define TRACE_COUNTER2(category, name, value1_name, value1_val, value2_name, \
|
||||||
value2_val) \
|
value2_val) \
|
||||||
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
||||||
@ -267,28 +301,32 @@
|
|||||||
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
||||||
value2_val, true)
|
value2_val, true)
|
||||||
|
|
||||||
// Records the value of a counter called "name" immediately. Value
|
///
|
||||||
// must be representable as a 32 bit integer.
|
/// Records the value of a counter called "name" immediately. Value
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// must be representable as a 32 bit integer.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
// - |id| is used to disambiguate counters with the same name. It must either
|
/// literals). They may not include " chars.
|
||||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
/// - |id| is used to disambiguate counters with the same name. It must either
|
||||||
// bits will be xored with a hash of the process ID so that the same pointer
|
/// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
||||||
// on two different processes will not collide.
|
/// bits will be xored with a hash of the process ID so that the same pointer
|
||||||
|
/// on two different processes will not collide.
|
||||||
|
///
|
||||||
#define TRACE_COUNTER_ID1(category, name, id, value) \
|
#define TRACE_COUNTER_ID1(category, name, id, value) \
|
||||||
cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false)
|
cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false)
|
||||||
#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
|
#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
|
||||||
cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true)
|
cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true)
|
||||||
|
|
||||||
// Records the values of a multi-parted counter called "name" immediately.
|
///
|
||||||
// The UI will treat value1 and value2 as parts of a whole, displaying their
|
/// Records the values of a multi-parted counter called "name" immediately.
|
||||||
// values as a stacked-bar chart.
|
/// The UI will treat value1 and value2 as parts of a whole, displaying their
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// values as a stacked-bar chart.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
// - |id| is used to disambiguate counters with the same name. It must either
|
/// literals). They may not include " chars.
|
||||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
/// - |id| is used to disambiguate counters with the same name. It must either
|
||||||
// bits will be xored with a hash of the process ID so that the same pointer
|
/// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
||||||
// on two different processes will not collide.
|
/// bits will be xored with a hash of the process ID so that the same pointer
|
||||||
|
/// on two different processes will not collide.
|
||||||
|
///
|
||||||
#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
|
#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
|
||||||
value2_name, value2_val) \
|
value2_name, value2_val) \
|
||||||
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
||||||
@ -298,22 +336,24 @@
|
|||||||
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
||||||
value2_name, value2_val, true)
|
value2_name, value2_val, true)
|
||||||
|
|
||||||
// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
|
///
|
||||||
// associated arguments. If the category is not enabled, then this
|
/// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
|
||||||
// does nothing.
|
/// associated arguments. If the category is not enabled, then this
|
||||||
// - category and name strings must have application lifetime (statics or
|
/// does nothing.
|
||||||
// literals). They may not include " chars.
|
/// - category and name strings must have application lifetime (statics or
|
||||||
// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
|
/// literals). They may not include " chars.
|
||||||
// ASYNC events are considered to match if their category, name and id values
|
/// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
|
||||||
// all match. |id| must either be a pointer or an integer value up to 64
|
/// ASYNC events are considered to match if their category, name and id values
|
||||||
// bits. If it's a pointer, the bits will be xored with a hash of the process
|
/// all match. |id| must either be a pointer or an integer value up to 64
|
||||||
// ID sothat the same pointer on two different processes will not collide.
|
/// bits. If it's a pointer, the bits will be xored with a hash of the process
|
||||||
// An asynchronous operation can consist of multiple phases. The first phase is
|
/// ID sothat the same pointer on two different processes will not collide.
|
||||||
// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
|
/// An asynchronous operation can consist of multiple phases. The first phase is
|
||||||
// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
|
/// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
|
||||||
// An async operation can span threads and processes, but all events in that
|
/// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
|
||||||
// operation must use the same |name| and |id|. Each event can have its own
|
/// An async operation can span threads and processes, but all events in that
|
||||||
// args.
|
/// operation must use the same |name| and |id|. Each event can have its own
|
||||||
|
/// args.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
|
#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
|
||||||
cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false)
|
cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false)
|
||||||
#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
||||||
@ -333,12 +373,14 @@
|
|||||||
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
|
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
|
||||||
arg2_name, arg2_val, true)
|
arg2_name, arg2_val, true)
|
||||||
|
|
||||||
// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
|
///
|
||||||
// category is not enabled, then this does nothing. The |name| and |id| must
|
/// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
|
||||||
// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
/// category is not enabled, then this does nothing. The |name| and |id| must
|
||||||
// within the async event. This should be called at the beginning of the next
|
/// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
||||||
// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
|
/// within the async event. This should be called at the beginning of the next
|
||||||
// ASYNC_STEP_PAST events.
|
/// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
|
||||||
|
/// ASYNC_STEP_PAST events.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \
|
#define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \
|
||||||
cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false)
|
cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false)
|
||||||
#define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \
|
#define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \
|
||||||
@ -352,12 +394,14 @@
|
|||||||
cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
|
cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
|
||||||
arg1_val, true)
|
arg1_val, true)
|
||||||
|
|
||||||
// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
|
///
|
||||||
// category is not enabled, then this does nothing. The |name| and |id| must
|
/// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
|
||||||
// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
/// category is not enabled, then this does nothing. The |name| and |id| must
|
||||||
// within the async event. This should be called at the beginning of the next
|
/// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
||||||
// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
|
/// within the async event. This should be called at the beginning of the next
|
||||||
// ASYNC_STEP_INTO events.
|
/// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
|
||||||
|
/// ASYNC_STEP_INTO events.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \
|
#define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \
|
||||||
cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false)
|
cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false)
|
||||||
#define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \
|
#define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \
|
||||||
@ -371,8 +415,10 @@
|
|||||||
cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
|
cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
|
||||||
arg1_val, true)
|
arg1_val, true)
|
||||||
|
|
||||||
// Records a single ASYNC_END event for "name" immediately. If the category
|
///
|
||||||
// is not enabled, then this does nothing.
|
/// Records a single ASYNC_END event for "name" immediately. If the category
|
||||||
|
/// is not enabled, then this does nothing.
|
||||||
|
///
|
||||||
#define TRACE_EVENT_ASYNC_END0(category, name, id) \
|
#define TRACE_EVENT_ASYNC_END0(category, name, id) \
|
||||||
cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false)
|
cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false)
|
||||||
#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
|
#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
|
||||||
@ -394,7 +440,9 @@
|
|||||||
|
|
||||||
namespace cef_trace_event {
|
namespace cef_trace_event {
|
||||||
|
|
||||||
// Used by TRACE_EVENTx macro. Do not use directly.
|
///
|
||||||
|
/// Used by TRACE_EVENTx macro. Do not use directly.
|
||||||
|
///
|
||||||
class CefTraceEndOnScopeClose {
|
class CefTraceEndOnScopeClose {
|
||||||
public:
|
public:
|
||||||
CefTraceEndOnScopeClose(const char* category, const char* name)
|
CefTraceEndOnScopeClose(const char* category, const char* name)
|
||||||
@ -408,7 +456,7 @@ class CefTraceEndOnScopeClose {
|
|||||||
const char* name_;
|
const char* name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // cef_trace_event
|
} // namespace cef_trace_event
|
||||||
|
|
||||||
#endif // !USING_CHROMIUM_INCLUDES
|
#endif // !USING_CHROMIUM_INCLUDES
|
||||||
|
|
||||||
|
@ -28,25 +28,30 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// Use std::tuple as tuple type. This file contains helper functions for
|
///
|
||||||
// working with std::tuples.
|
/// \file
|
||||||
// The functions DispatchToMethod and DispatchToFunction take a function pointer
|
/// Use std::tuple as tuple type. This file contains helper functions for
|
||||||
// or instance and method pointer, and unpack a tuple into arguments to the
|
/// working with std::tuples.
|
||||||
// call.
|
/// The functions DispatchToMethod and DispatchToFunction take a function
|
||||||
//
|
/// pointer or instance and method pointer, and unpack a tuple into arguments to
|
||||||
// Example usage:
|
/// the call.
|
||||||
// // These two methods of creating a Tuple are identical.
|
///
|
||||||
// std::tuple<int, const char*> tuple_a(1, "wee");
|
/// Example usage:
|
||||||
// std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee");
|
/// <pre>
|
||||||
//
|
/// // These two methods of creating a Tuple are identical.
|
||||||
// void SomeFunc(int a, const char* b) { }
|
/// std::tuple<int, const char*> tuple_a(1, "wee");
|
||||||
// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee")
|
/// std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee");
|
||||||
// DispatchToFunction(
|
///
|
||||||
// &SomeFunc, std::make_tuple(10, "foo")); // SomeFunc(10, "foo")
|
/// void SomeFunc(int a, const char* b) { }
|
||||||
//
|
/// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee")
|
||||||
// struct { void SomeMeth(int a, int b, int c) { } } foo;
|
/// DispatchToFunction(
|
||||||
// DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3));
|
/// &SomeFunc, std::make_tuple(10, "foo")); // SomeFunc(10, "foo")
|
||||||
// // foo->SomeMeth(1, 2, 3);
|
///
|
||||||
|
/// struct { void SomeMeth(int a, int b, int c) { } } foo;
|
||||||
|
/// DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3));
|
||||||
|
/// // foo->SomeMeth(1, 2, 3);
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_TUPLE_H_
|
#define CEF_INCLUDE_BASE_CEF_TUPLE_H_
|
||||||
@ -88,9 +93,7 @@ inline void DispatchToMethodImpl(const ObjT& obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ObjT, typename Method, typename Tuple>
|
template <typename ObjT, typename Method, typename Tuple>
|
||||||
inline void DispatchToMethod(const ObjT& obj,
|
inline void DispatchToMethod(const ObjT& obj, Method method, Tuple&& args) {
|
||||||
Method method,
|
|
||||||
Tuple&& args) {
|
|
||||||
constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
|
constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
|
||||||
DispatchToMethodImpl(obj, method, std::forward<Tuple>(args),
|
DispatchToMethodImpl(obj, method, std::forward<Tuple>(args),
|
||||||
std::make_index_sequence<size>());
|
std::make_index_sequence<size>());
|
||||||
|
@ -28,69 +28,73 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// Weak pointers are pointers to an object that do not affect its lifetime,
|
///
|
||||||
// and which may be invalidated (i.e. reset to nullptr) by the object, or its
|
/// \file
|
||||||
// owner, at any time, most commonly when the object is about to be deleted.
|
/// Weak pointers are pointers to an object that do not affect its lifetime.
|
||||||
|
/// They may be invalidated (i.e. reset to nullptr) by the object, or its
|
||||||
// Weak pointers are useful when an object needs to be accessed safely by one
|
/// owner, at any time, most commonly when the object is about to be deleted.
|
||||||
// or more objects other than its owner, and those callers can cope with the
|
///
|
||||||
// object vanishing and e.g. tasks posted to it being silently dropped.
|
/// Weak pointers are useful when an object needs to be accessed safely by one
|
||||||
// Reference-counting such an object would complicate the ownership graph and
|
/// or more objects other than its owner, and those callers can cope with the
|
||||||
// make it harder to reason about the object's lifetime.
|
/// object vanishing and e.g. tasks posted to it being silently dropped.
|
||||||
|
/// Reference-counting such an object would complicate the ownership graph and
|
||||||
// EXAMPLE:
|
/// make it harder to reason about the object's lifetime.
|
||||||
//
|
///
|
||||||
// class Controller {
|
/// EXAMPLE:
|
||||||
// public:
|
///
|
||||||
// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
|
/// <pre>
|
||||||
// void WorkComplete(const Result& result) { ... }
|
/// class Controller {
|
||||||
// private:
|
/// public:
|
||||||
// // Member variables should appear before the WeakPtrFactory, to ensure
|
/// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
|
||||||
// // that any WeakPtrs to Controller are invalidated before its members
|
/// void WorkComplete(const Result& result) { ... }
|
||||||
// // variable's destructors are executed, rendering them invalid.
|
/// private:
|
||||||
// WeakPtrFactory<Controller> weak_factory_{this};
|
/// // Member variables should appear before the WeakPtrFactory, to ensure
|
||||||
// };
|
/// // that any WeakPtrs to Controller are invalidated before its members
|
||||||
//
|
/// // variable's destructors are executed, rendering them invalid.
|
||||||
// class Worker {
|
/// WeakPtrFactory<Controller> weak_factory_{this};
|
||||||
// public:
|
/// };
|
||||||
// static void StartNew(WeakPtr<Controller> controller) {
|
///
|
||||||
// Worker* worker = new Worker(std::move(controller));
|
/// class Worker {
|
||||||
// // Kick off asynchronous processing...
|
/// public:
|
||||||
// }
|
/// static void StartNew(WeakPtr<Controller> controller) {
|
||||||
// private:
|
/// Worker* worker = new Worker(std::move(controller));
|
||||||
// Worker(WeakPtr<Controller> controller)
|
/// // Kick off asynchronous processing...
|
||||||
// : controller_(std::move(controller)) {}
|
/// }
|
||||||
// void DidCompleteAsynchronousProcessing(const Result& result) {
|
/// private:
|
||||||
// if (controller_)
|
/// Worker(WeakPtr<Controller> controller)
|
||||||
// controller_->WorkComplete(result);
|
/// : controller_(std::move(controller)) {}
|
||||||
// }
|
/// void DidCompleteAsynchronousProcessing(const Result& result) {
|
||||||
// WeakPtr<Controller> controller_;
|
/// if (controller_)
|
||||||
// };
|
/// controller_->WorkComplete(result);
|
||||||
//
|
/// }
|
||||||
// With this implementation a caller may use SpawnWorker() to dispatch multiple
|
/// WeakPtr<Controller> controller_;
|
||||||
// Workers and subsequently delete the Controller, without waiting for all
|
/// };
|
||||||
// Workers to have completed.
|
/// </pre>
|
||||||
|
///
|
||||||
// ------------------------- IMPORTANT: Thread-safety -------------------------
|
/// With this implementation a caller may use SpawnWorker() to dispatch multiple
|
||||||
|
/// Workers and subsequently delete the Controller, without waiting for all
|
||||||
// Weak pointers may be passed safely between threads, but must always be
|
/// Workers to have completed.
|
||||||
// dereferenced and invalidated on the same ThreaddTaskRunner otherwise
|
///
|
||||||
// checking the pointer would be racey.
|
/// <b>IMPORTANT: Thread-safety</b>
|
||||||
//
|
///
|
||||||
// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
|
/// Weak pointers may be passed safely between threads, but must always be
|
||||||
// is dereferenced, the factory and its WeakPtrs become bound to the calling
|
/// dereferenced and invalidated on the same ThreaddTaskRunner otherwise
|
||||||
// thread or current ThreaddWorkerPool token, and cannot be dereferenced or
|
/// checking the pointer would be racey.
|
||||||
// invalidated on any other task runner. Bound WeakPtrs can still be handed
|
///
|
||||||
// off to other task runners, e.g. to use to post tasks back to object on the
|
/// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
|
||||||
// bound thread.
|
/// is dereferenced, the factory and its WeakPtrs become bound to the calling
|
||||||
//
|
/// thread or current ThreaddWorkerPool token, and cannot be dereferenced or
|
||||||
// If all WeakPtr objects are destroyed or invalidated then the factory is
|
/// invalidated on any other task runner. Bound WeakPtrs can still be handed
|
||||||
// unbound from the ThreaddTaskRunner/Thread. The WeakPtrFactory may then be
|
/// off to other task runners, e.g. to use to post tasks back to object on the
|
||||||
// destroyed, or new WeakPtr objects may be used, from a different thread.
|
/// bound thread.
|
||||||
//
|
///
|
||||||
// Thus, at least one WeakPtr object must exist and have been dereferenced on
|
/// If all WeakPtr objects are destroyed or invalidated then the factory is
|
||||||
// the correct thread to enforce that other WeakPtr objects will enforce they
|
/// unbound from the ThreadedTaskRunner/Thread. The WeakPtrFactory may then be
|
||||||
// are used on the desired thread.
|
/// destroyed, or new WeakPtr objects may be used, from a different thread.
|
||||||
|
///
|
||||||
|
/// Thus, at least one WeakPtr object must exist and have been dereferenced on
|
||||||
|
/// the correct thread to enforce that other WeakPtr objects will enforce they
|
||||||
|
/// are used on the desired thread.
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
#ifndef CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
||||||
#define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
#define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
||||||
@ -243,27 +247,32 @@ class SupportsWeakPtrBase {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class WeakPtrFactory;
|
class WeakPtrFactory;
|
||||||
|
|
||||||
// The WeakPtr class holds a weak reference to |T*|.
|
///
|
||||||
//
|
/// The WeakPtr class holds a weak reference to |T*|.
|
||||||
// This class is designed to be used like a normal pointer. You should always
|
///
|
||||||
// null-test an object of this class before using it or invoking a method that
|
/// This class is designed to be used like a normal pointer. You should always
|
||||||
// may result in the underlying object being destroyed.
|
/// null-test an object of this class before using it or invoking a method that
|
||||||
//
|
/// may result in the underlying object being destroyed.
|
||||||
// EXAMPLE:
|
///
|
||||||
//
|
/// EXAMPLE:
|
||||||
// class Foo { ... };
|
///
|
||||||
// WeakPtr<Foo> foo;
|
/// <pre>
|
||||||
// if (foo)
|
/// class Foo { ... };
|
||||||
// foo->method();
|
/// WeakPtr<Foo> foo;
|
||||||
//
|
/// if (foo)
|
||||||
|
/// foo->method();
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class WeakPtr : public internal::WeakPtrBase {
|
class WeakPtr : public internal::WeakPtrBase {
|
||||||
public:
|
public:
|
||||||
WeakPtr() = default;
|
WeakPtr() = default;
|
||||||
WeakPtr(std::nullptr_t) {}
|
WeakPtr(std::nullptr_t) {}
|
||||||
|
|
||||||
// Allow conversion from U to T provided U "is a" T. Note that this
|
///
|
||||||
// is separate from the (implicit) copy and move constructors.
|
/// Allow conversion from U to T provided U "is a" T. Note that this
|
||||||
|
/// is separate from the (implicit) copy and move constructors.
|
||||||
|
///
|
||||||
template <typename U>
|
template <typename U>
|
||||||
WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) {
|
WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) {
|
||||||
// Need to cast from U* to T* to do pointer adjustment in case of multiple
|
// Need to cast from U* to T* to do pointer adjustment in case of multiple
|
||||||
@ -292,21 +301,27 @@ class WeakPtr : public internal::WeakPtrBase {
|
|||||||
return get();
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow conditionals to test validity, e.g. if (weak_ptr) {...};
|
///
|
||||||
|
/// Allow conditionals to test validity, e.g. `if (weak_ptr) {...}`;
|
||||||
|
///
|
||||||
explicit operator bool() const { return get() != nullptr; }
|
explicit operator bool() const { return get() != nullptr; }
|
||||||
|
|
||||||
// Returns false if the WeakPtr is confirmed to be invalid. This call is safe
|
///
|
||||||
// to make from any thread, e.g. to optimize away unnecessary work, but
|
/// Returns false if the WeakPtr is confirmed to be invalid. This call is safe
|
||||||
// operator bool() must always be called, on the correct thread, before
|
/// to make from any thread, e.g. to optimize away unnecessary work, but
|
||||||
// actually using the pointer.
|
/// operator bool() must always be called, on the correct thread, before
|
||||||
//
|
/// actually using the pointer.
|
||||||
// Warning: as with any object, this call is only thread-safe if the WeakPtr
|
///
|
||||||
// instance isn't being re-assigned or reset() racily with this call.
|
/// Warning: as with any object, this call is only thread-safe if the WeakPtr
|
||||||
|
/// instance isn't being re-assigned or reset() racily with this call.
|
||||||
|
///
|
||||||
bool MaybeValid() const { return ref_.MaybeValid(); }
|
bool MaybeValid() const { return ref_.MaybeValid(); }
|
||||||
|
|
||||||
// Returns whether the object |this| points to has been invalidated. This can
|
///
|
||||||
// be used to distinguish a WeakPtr to a destroyed object from one that has
|
/// Returns whether the object |this| points to has been invalidated. This can
|
||||||
// been explicitly set to null.
|
/// be used to distinguish a WeakPtr to a destroyed object from one that has
|
||||||
|
/// been explicitly set to null.
|
||||||
|
///
|
||||||
bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); }
|
bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -320,7 +335,9 @@ class WeakPtr : public internal::WeakPtrBase {
|
|||||||
: WeakPtrBase(ref, reinterpret_cast<uintptr_t>(ptr)) {}
|
: WeakPtrBase(ref, reinterpret_cast<uintptr_t>(ptr)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow callers to compare WeakPtrs against nullptr to test validity.
|
///
|
||||||
|
/// Allow callers to compare WeakPtrs against nullptr to test validity.
|
||||||
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
||||||
return !(weak_ptr == nullptr);
|
return !(weak_ptr == nullptr);
|
||||||
@ -348,11 +365,14 @@ class WeakPtrFactoryBase {
|
|||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// A class may be composed of a WeakPtrFactory and thereby
|
///
|
||||||
// control how it exposes weak pointers to itself. This is helpful if you only
|
/// A class may be composed of a WeakPtrFactory and thereby control how it
|
||||||
// need weak pointers within the implementation of a class. This class is also
|
/// exposes weak pointers to itself. This is helpful if you only need weak
|
||||||
// useful when working with primitive types. For example, you could have a
|
/// pointers within the implementation of a class. This class is also useful
|
||||||
// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
|
/// when working with primitive types. For example, you could have a
|
||||||
|
/// WeakPtrFactory<bool> that is used to pass around a weak reference to a
|
||||||
|
/// bool.
|
||||||
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
class WeakPtrFactory : public internal::WeakPtrFactoryBase {
|
class WeakPtrFactory : public internal::WeakPtrFactoryBase {
|
||||||
public:
|
public:
|
||||||
@ -371,24 +391,30 @@ class WeakPtrFactory : public internal::WeakPtrFactoryBase {
|
|||||||
reinterpret_cast<T*>(ptr_));
|
reinterpret_cast<T*>(ptr_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this method to invalidate all existing weak pointers.
|
///
|
||||||
|
/// Call this method to invalidate all existing weak pointers.
|
||||||
|
///
|
||||||
void InvalidateWeakPtrs() {
|
void InvalidateWeakPtrs() {
|
||||||
DCHECK(ptr_);
|
DCHECK(ptr_);
|
||||||
weak_reference_owner_.Invalidate();
|
weak_reference_owner_.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this method to determine if any weak pointers exist.
|
///
|
||||||
|
/// Call this method to determine if any weak pointers exist.
|
||||||
|
///
|
||||||
bool HasWeakPtrs() const {
|
bool HasWeakPtrs() const {
|
||||||
DCHECK(ptr_);
|
DCHECK(ptr_);
|
||||||
return weak_reference_owner_.HasRefs();
|
return weak_reference_owner_.HasRefs();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A class may extend from SupportsWeakPtr to let others take weak pointers to
|
///
|
||||||
// it. This avoids the class itself implementing boilerplate to dispense weak
|
/// A class may extend from SupportsWeakPtr to let others take weak pointers to
|
||||||
// pointers. However, since SupportsWeakPtr's destructor won't invalidate
|
/// it. This avoids the class itself implementing boilerplate to dispense weak
|
||||||
// weak pointers to the class until after the derived class' members have been
|
/// pointers. However, since SupportsWeakPtr's destructor won't invalidate
|
||||||
// destroyed, its use can lead to subtle use-after-destroy issues.
|
/// weak pointers to the class until after the derived class' members have been
|
||||||
|
/// destroyed, its use can lead to subtle use-after-destroy issues.
|
||||||
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
|
class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
|
||||||
public:
|
public:
|
||||||
@ -408,24 +434,29 @@ class SupportsWeakPtr : public internal::SupportsWeakPtrBase {
|
|||||||
internal::WeakReferenceOwner weak_reference_owner_;
|
internal::WeakReferenceOwner weak_reference_owner_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function that uses type deduction to safely return a WeakPtr<Derived>
|
///
|
||||||
// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
|
/// Helper function that uses type deduction to safely return a WeakPtr<Derived>
|
||||||
// extends a Base that extends SupportsWeakPtr<Base>.
|
/// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
|
||||||
//
|
/// extends a Base that extends SupportsWeakPtr<Base>.
|
||||||
// EXAMPLE:
|
///
|
||||||
// class Base : public base::SupportsWeakPtr<Producer> {};
|
/// EXAMPLE:
|
||||||
// class Derived : public Base {};
|
/// <pre>
|
||||||
//
|
/// class Base : public base::SupportsWeakPtr<Producer> {};
|
||||||
// Derived derived;
|
/// class Derived : public Base {};
|
||||||
// base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
|
///
|
||||||
//
|
/// Derived derived;
|
||||||
// Note that the following doesn't work (invalid type conversion) since
|
/// base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
|
||||||
// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
|
/// </pre>
|
||||||
// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
|
///
|
||||||
// the caller.
|
/// Note that the following doesn't work (invalid type conversion) since
|
||||||
//
|
/// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
|
||||||
// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
|
/// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
|
||||||
|
/// the caller.
|
||||||
|
///
|
||||||
|
/// <pre>
|
||||||
|
/// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
|
||||||
|
/// </pre>
|
||||||
|
///
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
WeakPtr<Derived> AsWeakPtr(Derived* t) {
|
WeakPtr<Derived> AsWeakPtr(Derived* t) {
|
||||||
return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
|
return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
|
||||||
|
Reference in New Issue
Block a user