mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Create 2272 release branch for CEF3.
git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/2272@1993 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
126
include/base/cef_atomic_ref_count.h
Normal file
126
include/base/cef_atomic_ref_count.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This is a low level implementation of atomic semantics for reference
|
||||
// counting. Please use cef_ref_counted.h directly instead.
|
||||
//
|
||||
// The Chromium implementation includes annotations to avoid some false
|
||||
// positives when using data race detection tools. Annotations are not
|
||||
// currently supported by the CEF implementation.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_ATOMIC_REF_COUNT_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/atomic_ref_count.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_atomicops.h"
|
||||
|
||||
// Annotations are not currently supported.
|
||||
#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
|
||||
#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
|
||||
|
||||
namespace base {
|
||||
|
||||
typedef subtle::Atomic32 AtomicRefCount;
|
||||
|
||||
// Increment a reference count by "increment", which must exceed 0.
|
||||
inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
|
||||
AtomicRefCount increment) {
|
||||
subtle::NoBarrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
// Decrement a reference count by "decrement", which must exceed 0,
|
||||
// and return whether the result is non-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.
|
||||
inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
|
||||
AtomicRefCount decrement) {
|
||||
ANNOTATE_HAPPENS_BEFORE(ptr);
|
||||
bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
|
||||
if (!res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Increment a reference count by 1.
|
||||
inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
|
||||
base::AtomicRefCountIncN(ptr, 1);
|
||||
}
|
||||
|
||||
// Decrement a reference count by 1 and return whether the result is non-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.
|
||||
inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
|
||||
return base::AtomicRefCountDecN(ptr, 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
|
||||
// thread owns the reference and no other thread shares it. This call performs
|
||||
// the test for a reference count of one, and performs the memory barrier
|
||||
// needed for the owning thread to act on the object, knowing that it has
|
||||
// exclusive access to the object.
|
||||
inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
|
||||
bool res = (subtle::Acquire_Load(ptr) == 1);
|
||||
if (res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Return whether the reference count is zero. With conventional object
|
||||
// referencing counting, the object will be destroyed, so the reference count
|
||||
// should never be zero. Hence this is generally used for a debug check.
|
||||
inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
|
||||
bool res = (subtle::Acquire_Load(ptr) == 0);
|
||||
if (res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
198
include/base/cef_atomicops.h
Normal file
198
include/base/cef_atomicops.h
Normal file
@ -0,0 +1,198 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// For atomic operations on reference counts, see cef_atomic_ref_count.h.
|
||||
|
||||
// The routines exported by this module are subtle. If you use them, even if
|
||||
// you get the code right, it will depend on careful reasoning about atomicity
|
||||
// and memory ordering; it will be less readable, and harder to maintain. If
|
||||
// you plan to use these routines, you should have a good reason, such as solid
|
||||
// evidence that performance would otherwise suffer, or there being no
|
||||
// alternative. You should assume only properties explicitly guaranteed by the
|
||||
// specifications in this file. You are almost certainly _not_ writing code
|
||||
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
|
||||
// implementations on other archtectures will cause your code to break. If you
|
||||
// do not know what you are doing, avoid these routines, and use a Mutex.
|
||||
//
|
||||
// It is incorrect to make direct assignments to/from an atomic variable.
|
||||
// You should use one of the Load or Store routines. The NoBarrier
|
||||
// versions are provided when no barriers are needed:
|
||||
// NoBarrier_Store()
|
||||
// NoBarrier_Load()
|
||||
// Although there are currently no compiler enforcement, you are encouraged
|
||||
// to use these.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_ATOMICOPS_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/atomicops.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
|
||||
// windows.h #defines this (only on x64). This causes problems because the
|
||||
// public API also uses MemoryBarrier at the public name for this fence. So, on
|
||||
// X64, undef it, and call its documented
|
||||
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
|
||||
// implementation directly.
|
||||
#undef MemoryBarrier
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
typedef int32_t Atomic32;
|
||||
#ifdef ARCH_CPU_64_BITS
|
||||
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
|
||||
// means Atomic64 and AtomicWord should be the same type on 64-bit.
|
||||
#if defined(__ILP32__) || defined(OS_NACL)
|
||||
// NaCl's intptr_t is not actually 64-bits on 64-bit!
|
||||
// http://code.google.com/p/nativeclient/issues/detail?id=1162
|
||||
typedef int64_t Atomic64;
|
||||
#else
|
||||
typedef intptr_t Atomic64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
|
||||
// Atomic64 routines below, depending on your architecture.
|
||||
typedef intptr_t AtomicWord;
|
||||
|
||||
// Atomically execute:
|
||||
// result = *ptr;
|
||||
// if (*ptr == old_value)
|
||||
// *ptr = new_value;
|
||||
// return result;
|
||||
//
|
||||
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
|
||||
// Always return the old value of "*ptr"
|
||||
//
|
||||
// This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
// Atomically store new_value into *ptr, returning the previous value held in
|
||||
// *ptr. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
|
||||
|
||||
// Atomically increment *ptr by "increment". Returns the new value of
|
||||
// *ptr with the increment applied. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
|
||||
|
||||
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment);
|
||||
|
||||
// These following lower-level operations are typically useful only to people
|
||||
// implementing higher-level synchronization operations like spinlocks,
|
||||
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
|
||||
// a store with appropriate memory-ordering instructions. "Acquire" operations
|
||||
// ensure that no later memory access can be reordered ahead of the operation.
|
||||
// "Release" operations ensure that no previous memory access can be reordered
|
||||
// after the operation. "Barrier" operations have both "Acquire" and "Release"
|
||||
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
|
||||
// access.
|
||||
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
void MemoryBarrier();
|
||||
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
|
||||
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Release_Load(volatile const Atomic32* ptr);
|
||||
|
||||
// 64-bit atomic operations (only available on 64-bit processors).
|
||||
#ifdef ARCH_CPU_64_BITS
|
||||
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
|
||||
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Release_Load(volatile const Atomic64* ptr);
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
} // namespace subtle
|
||||
} // namespace base
|
||||
|
||||
// Include our platform specific implementation.
|
||||
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
#include "include/base/internal/cef_atomicops_x86_msvc.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "include/base/internal/cef_atomicops_mac.h"
|
||||
#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
#include "include/base/internal/cef_atomicops_x86_gcc.h"
|
||||
#else
|
||||
#error "Atomic operations are not supported on your platform"
|
||||
#endif
|
||||
|
||||
// On some platforms we need additional declarations to make
|
||||
// AtomicWord compatible with our other Atomic* types.
|
||||
#if defined(OS_MACOSX) || defined(OS_OPENBSD)
|
||||
#include "include/base/internal/cef_atomicops_atomicword_compat.h"
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
86
include/base/cef_basictypes.h
Normal file
86
include/base/cef_basictypes.h
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/basictypes.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <limits.h> // For UINT_MAX
|
||||
#include <stddef.h> // For size_t
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
// The NSPR system headers define 64-bit as |long| when possible, except on
|
||||
// Mac OS X. In order to not have typedef mismatches, we do the same on LP64.
|
||||
//
|
||||
// On Mac OS X, |long long| is used for 64-bit types for compatibility with
|
||||
// <inttypes.h> format macros even in the LP64 model.
|
||||
#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
|
||||
typedef long int64; // NOLINT(runtime/int)
|
||||
typedef unsigned long uint64; // NOLINT(runtime/int)
|
||||
#else
|
||||
typedef long long int64; // NOLINT(runtime/int)
|
||||
typedef unsigned long long uint64; // NOLINT(runtime/int)
|
||||
#endif
|
||||
|
||||
// TODO: Remove these type guards. These are to avoid conflicts with
|
||||
// obsolete/protypes.h in the Gecko SDK.
|
||||
#ifndef _INT32
|
||||
#define _INT32
|
||||
typedef int int32;
|
||||
#endif
|
||||
|
||||
// TODO: Remove these type guards. These are to avoid conflicts with
|
||||
// obsolete/protypes.h in the Gecko SDK.
|
||||
#ifndef _UINT32
|
||||
#define _UINT32
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
|
||||
// UTF-16 character type
|
||||
#ifndef char16
|
||||
#if defined(WIN32)
|
||||
typedef wchar_t char16;
|
||||
#else
|
||||
typedef unsigned short char16;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
548
include/base/cef_bind.h
Normal file
548
include/base/cef_bind.h
Normal file
@ -0,0 +1,548 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_BIND_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_BIND_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_BIND_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/bind.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/internal/cef_bind_internal.h"
|
||||
#include "include/base/internal/cef_callback_internal.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Usage documentation
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// See base/cef_callback.h for documentation.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation notes
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// If you're reading the implementation, before proceeding further, you should
|
||||
// read the top comment of base/bind_internal.h for a definition of common
|
||||
// terms and concepts.
|
||||
//
|
||||
// RETURN TYPES
|
||||
//
|
||||
// Though Bind()'s result is meant to be stored in a Callback<> type, it
|
||||
// cannot actually return the exact type without requiring a large amount
|
||||
// of extra template specializations. The problem is that in order to
|
||||
// discern the correct specialization of Callback<>, Bind would need to
|
||||
// unwrap the function signature to determine the signature's arity, and
|
||||
// whether or not it is a method.
|
||||
//
|
||||
// Each unique combination of (arity, function_type, num_prebound) where
|
||||
// function_type is one of {function, method, const_method} would require
|
||||
// one specialization. We eventually have to do a similar number of
|
||||
// specializations anyways in the implementation (see the Invoker<>,
|
||||
// classes). However, it is avoidable in Bind if we return the result
|
||||
// via an indirection like we do below.
|
||||
//
|
||||
// TODO(ajwong): We might be able to avoid this now, but need to test.
|
||||
//
|
||||
// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>,
|
||||
// but it feels a little nicer to have the asserts here so people do not
|
||||
// need to crack open bind_internal.h. On the other hand, it makes Bind()
|
||||
// harder to read.
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Functor>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void()>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
typedef cef_internal::BindState<RunnableType, RunType, void()> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor)));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2, typename P3>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
|
||||
p3_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2, typename P3, typename P4>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
|
||||
p3_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
|
||||
p4_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
|
||||
typename P5>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
|
||||
const P5& p5) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
|
||||
p3_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
|
||||
p4_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
|
||||
p5_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
|
||||
typename P5, typename P6>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P6>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
|
||||
const P5& p5, const P6& p6) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
|
||||
p3_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
|
||||
p4_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
|
||||
p5_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
|
||||
p6_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P6>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
|
||||
}
|
||||
|
||||
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
|
||||
typename P5, typename P6, typename P7>
|
||||
base::Callback<
|
||||
typename cef_internal::BindState<
|
||||
typename cef_internal::FunctorTraits<Functor>::RunnableType,
|
||||
typename cef_internal::FunctorTraits<Functor>::RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P6>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P7>::StorageType)>
|
||||
::UnboundRunType>
|
||||
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
|
||||
const P5& p5, const P6& p6, const P7& p7) {
|
||||
// Typedefs for how to store and run the functor.
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
|
||||
typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
|
||||
|
||||
// Use RunnableType::RunType instead of RunType above because our
|
||||
// checks should below for bound references need to know what the actual
|
||||
// functor is going to interpret the argument as.
|
||||
typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
|
||||
BoundFunctorTraits;
|
||||
|
||||
// Do not allow binding a non-const reference parameter. Non-const reference
|
||||
// parameters are disallowed by the Google style guide. Also, binding a
|
||||
// non-const reference parameter can make for subtle bugs because the
|
||||
// invoked function will receive a reference to the stored copy of the
|
||||
// argument and not the original.
|
||||
COMPILE_ASSERT(
|
||||
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ||
|
||||
is_non_const_reference<typename BoundFunctorTraits::A7Type>::value ),
|
||||
do_not_bind_functions_with_nonconst_ref);
|
||||
|
||||
// For methods, we need to be careful for parameter 1. We do not require
|
||||
// a scoped_refptr because BindState<> itself takes care of AddRef() for
|
||||
// methods. We also disallow binding of an array as the method's target
|
||||
// object.
|
||||
COMPILE_ASSERT(
|
||||
cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
|
||||
p1_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
|
||||
!is_array<P1>::value,
|
||||
first_bound_argument_to_method_cannot_be_array);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
|
||||
p2_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
|
||||
p3_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
|
||||
p4_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
|
||||
p5_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
|
||||
p6_is_refcounted_type_and_needs_scoped_refptr);
|
||||
COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
|
||||
p7_is_refcounted_type_and_needs_scoped_refptr);
|
||||
typedef cef_internal::BindState<RunnableType, RunType,
|
||||
void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P2>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P3>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P4>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P5>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P6>::StorageType,
|
||||
typename cef_internal::CallbackParamTraits<P7>::StorageType)> BindState;
|
||||
|
||||
|
||||
return Callback<typename BindState::UnboundRunType>(
|
||||
new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6,
|
||||
p7));
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_BIND_H_
|
586
include/base/cef_bind_helpers.h
Normal file
586
include/base/cef_bind_helpers.h
Normal file
@ -0,0 +1,586 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This defines a set of argument wrappers and related factory methods that
|
||||
// can be used specify the refcounting and reference semantics of arguments
|
||||
// that are bound by the Bind() function in base/bind.h.
|
||||
//
|
||||
// It also defines a set of simple functions and utilities that people want
|
||||
// when using Callback<> and Bind().
|
||||
//
|
||||
//
|
||||
// ARGUMENT BINDING WRAPPERS
|
||||
//
|
||||
// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(),
|
||||
// base::ConstRef(), and base::IgnoreResult().
|
||||
//
|
||||
// Unretained() allows Bind() to bind a non-refcounted class, and to disable
|
||||
// refcounting on arguments that are refcounted objects.
|
||||
//
|
||||
// Owned() transfers ownership of an object to the Callback resulting from
|
||||
// bind; the object will be deleted when the Callback is deleted.
|
||||
//
|
||||
// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr)
|
||||
// through a Callback. Logically, this signifies a destructive transfer of
|
||||
// the state of the argument into the target function. Invoking
|
||||
// Callback::Run() twice on a Callback that was created with a Passed()
|
||||
// argument will CHECK() because the first invocation would have already
|
||||
// transferred ownership to the target function.
|
||||
//
|
||||
// ConstRef() allows binding a constant reference to an argument rather
|
||||
// than a copy.
|
||||
//
|
||||
// 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,
|
||||
// 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 Unretained():
|
||||
//
|
||||
// class Foo {
|
||||
// public:
|
||||
// void func() { cout << "Foo:f" << endl; }
|
||||
// };
|
||||
//
|
||||
// // In some function somewhere.
|
||||
// Foo foo;
|
||||
// Closure foo_callback =
|
||||
// Bind(&Foo::func, Unretained(&foo));
|
||||
// foo_callback.Run(); // Prints "Foo:f".
|
||||
//
|
||||
// Without the Unretained() wrapper on |&foo|, the above call would fail
|
||||
// to compile because Foo does not support the AddRef() and Release() methods.
|
||||
//
|
||||
//
|
||||
// EXAMPLE OF Owned():
|
||||
//
|
||||
// void foo(int* arg) { cout << *arg << endl }
|
||||
//
|
||||
// int* pn = new int(1);
|
||||
// Closure foo_callback = Bind(&foo, Owned(pn));
|
||||
//
|
||||
// foo_callback.Run(); // Prints "1"
|
||||
// foo_callback.Run(); // Prints "1"
|
||||
// *n = 2;
|
||||
// foo_callback.Run(); // Prints "2"
|
||||
//
|
||||
// foo_callback.Reset(); // |pn| is deleted. Also will happen when
|
||||
// // |foo_callback| goes out of scope.
|
||||
//
|
||||
// Without Owned(), someone would have to know to delete |pn| when the last
|
||||
// reference to the Callback is deleted.
|
||||
//
|
||||
//
|
||||
// EXAMPLE OF ConstRef():
|
||||
//
|
||||
// void foo(int arg) { cout << arg << endl }
|
||||
//
|
||||
// int n = 1;
|
||||
// Closure no_ref = Bind(&foo, n);
|
||||
// Closure has_ref = Bind(&foo, ConstRef(n));
|
||||
//
|
||||
// no_ref.Run(); // Prints "1"
|
||||
// has_ref.Run(); // Prints "1"
|
||||
//
|
||||
// n = 2;
|
||||
// no_ref.Run(); // Prints "1"
|
||||
// has_ref.Run(); // Prints "2"
|
||||
//
|
||||
// Note that because ConstRef() takes a reference on |n|, |n| must outlive all
|
||||
// its bound callbacks.
|
||||
//
|
||||
//
|
||||
// EXAMPLE OF IgnoreResult():
|
||||
//
|
||||
// int DoSomething(int arg) { cout << arg << endl; }
|
||||
//
|
||||
// // Assign to a Callback with a void return type.
|
||||
// Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething));
|
||||
// cb->Run(1); // Prints "1".
|
||||
//
|
||||
// // Prints "1" on |ml|.
|
||||
// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1);
|
||||
//
|
||||
//
|
||||
// EXAMPLE OF Passed():
|
||||
//
|
||||
// void TakesOwnership(scoped_ptr<Foo> arg) { }
|
||||
// scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); }
|
||||
//
|
||||
// scoped_ptr<Foo> f(new Foo());
|
||||
//
|
||||
// // |cb| is given ownership of Foo(). |f| is now NULL.
|
||||
// // You can use f.Pass() in place of &f, but it's more verbose.
|
||||
// Closure cb = Bind(&TakesOwnership, Passed(&f));
|
||||
//
|
||||
// // Run was never called so |cb| still owns Foo() and deletes
|
||||
// // it on Reset().
|
||||
// cb.Reset();
|
||||
//
|
||||
// // |cb| is given a new Foo created by CreateFoo().
|
||||
// cb = Bind(&TakesOwnership, Passed(CreateFoo()));
|
||||
//
|
||||
// // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
|
||||
// // no longer owns Foo() and, if reset, would not delete Foo().
|
||||
// cb.Run(); // Foo() is now transferred to |arg| and deleted.
|
||||
// cb.Run(); // This CHECK()s since Foo() already been used once.
|
||||
//
|
||||
// Passed() is particularly useful with PostTask() when you are transferring
|
||||
// ownership of an argument into a task, but don't necessarily know if the
|
||||
// task will always be executed. This can happen if the task is cancellable
|
||||
// or if it is posted to a MessageLoopProxy.
|
||||
//
|
||||
//
|
||||
// SIMPLE FUNCTIONS AND UTILITIES.
|
||||
//
|
||||
// DoNothing() - Useful for creating a Closure that does nothing when called.
|
||||
// DeletePointer<T>() - 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
|
||||
// fit.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_BIND_HELPERS_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/bind_helpers.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/cef_template_util.h"
|
||||
#include "include/base/cef_weak_ptr.h"
|
||||
|
||||
namespace base {
|
||||
namespace cef_internal {
|
||||
|
||||
// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T
|
||||
// for the existence of AddRef() and Release() functions of the correct
|
||||
// signature.
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
|
||||
// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
|
||||
// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison
|
||||
// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
|
||||
//
|
||||
// The last link in particular show the method used below.
|
||||
//
|
||||
// For SFINAE to work with inherited methods, we need to pull some extra tricks
|
||||
// with multiple inheritance. In the more standard formulation, the overloads
|
||||
// of Check would be:
|
||||
//
|
||||
// template <typename C>
|
||||
// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*);
|
||||
//
|
||||
// template <typename C>
|
||||
// No NotTheCheckWeWant(...);
|
||||
//
|
||||
// static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes);
|
||||
//
|
||||
// The problem here is that template resolution will not match
|
||||
// C::TargetFunc if TargetFunc does not exist directly in C. That is, if
|
||||
// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match,
|
||||
// |value| will be false. This formulation only checks for whether or
|
||||
// not TargetFunc exist directly in the class being introspected.
|
||||
//
|
||||
// To get around this, we play a dirty trick with multiple inheritance.
|
||||
// First, We create a class BaseMixin that declares each function that we
|
||||
// want to probe for. Then we create a class Base that inherits from both T
|
||||
// (the class we wish to probe) and BaseMixin. Note that the function
|
||||
// signature in BaseMixin does not need to match the signature of the function
|
||||
// we are probing for; thus it's easiest to just use void(void).
|
||||
//
|
||||
// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
|
||||
// ambiguous resolution between BaseMixin and T. This lets us write the
|
||||
// following:
|
||||
//
|
||||
// template <typename C>
|
||||
// No GoodCheck(Helper<&C::TargetFunc>*);
|
||||
//
|
||||
// template <typename C>
|
||||
// Yes GoodCheck(...);
|
||||
//
|
||||
// static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes);
|
||||
//
|
||||
// Notice here that the variadic version of GoodCheck() returns Yes here
|
||||
// instead of No like the previous one. Also notice that we calculate |value|
|
||||
// by specializing GoodCheck() on Base instead of T.
|
||||
//
|
||||
// We've reversed the roles of the variadic, and Helper overloads.
|
||||
// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid
|
||||
// substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve
|
||||
// to the variadic version if T has TargetFunc. If T::TargetFunc does not
|
||||
// exist, then &C::TargetFunc is not ambiguous, and the overload resolution
|
||||
// will prefer GoodCheck(Helper<&C::TargetFunc>*).
|
||||
//
|
||||
// This method of SFINAE will correctly probe for inherited names, but it cannot
|
||||
// typecheck those names. It's still a good enough sanity check though.
|
||||
//
|
||||
// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008.
|
||||
//
|
||||
// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted
|
||||
// this works well.
|
||||
//
|
||||
// TODO(ajwong): Make this check for Release() as well.
|
||||
// See http://crbug.com/82038.
|
||||
template <typename T>
|
||||
class SupportsAddRefAndRelease {
|
||||
typedef char Yes[1];
|
||||
typedef char No[2];
|
||||
|
||||
struct BaseMixin {
|
||||
void AddRef();
|
||||
};
|
||||
|
||||
// MSVC warns when you try to use Base if T has a private destructor, the
|
||||
// common pattern for refcounted types. It does this even though no attempt to
|
||||
// instantiate Base is made. We disable the warning for this definition.
|
||||
#if defined(OS_WIN)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4624)
|
||||
#endif
|
||||
struct Base : public T, public BaseMixin {
|
||||
};
|
||||
#if defined(OS_WIN)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <void(BaseMixin::*)(void)> struct Helper {};
|
||||
|
||||
template <typename C>
|
||||
static No& Check(Helper<&C::AddRef>*);
|
||||
|
||||
template <typename >
|
||||
static Yes& Check(...);
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes);
|
||||
};
|
||||
|
||||
// Helpers to assert that arguments of a recounted type are bound with a
|
||||
// scoped_refptr.
|
||||
template <bool IsClasstype, typename T>
|
||||
struct UnsafeBindtoRefCountedArgHelper : false_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnsafeBindtoRefCountedArgHelper<true, T>
|
||||
: integral_constant<bool, SupportsAddRefAndRelease<T>::value> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnsafeBindtoRefCountedArg : false_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnsafeBindtoRefCountedArg<T*>
|
||||
: UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class HasIsMethodTag {
|
||||
typedef char Yes[1];
|
||||
typedef char No[2];
|
||||
|
||||
template <typename U>
|
||||
static Yes& Check(typename U::IsMethod*);
|
||||
|
||||
template <typename U>
|
||||
static No& Check(...);
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class UnretainedWrapper {
|
||||
public:
|
||||
explicit UnretainedWrapper(T* o) : ptr_(o) {}
|
||||
T* get() const { return ptr_; }
|
||||
private:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ConstRefWrapper {
|
||||
public:
|
||||
explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
|
||||
const T& get() const { return *ptr_; }
|
||||
private:
|
||||
const T* ptr_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IgnoreResultHelper {
|
||||
explicit IgnoreResultHelper(T functor) : functor_(functor) {}
|
||||
|
||||
T functor_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IgnoreResultHelper<Callback<T> > {
|
||||
explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {}
|
||||
|
||||
const Callback<T>& functor_;
|
||||
};
|
||||
|
||||
// An alternate implementation is to avoid the destructive copy, and instead
|
||||
// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
|
||||
// a class that is essentially a scoped_ptr<>.
|
||||
//
|
||||
// The current implementation has the benefit though of leaving ParamTraits<>
|
||||
// fully in callback_internal.h as well as avoiding type conversions during
|
||||
// storage.
|
||||
template <typename T>
|
||||
class OwnedWrapper {
|
||||
public:
|
||||
explicit OwnedWrapper(T* o) : ptr_(o) {}
|
||||
~OwnedWrapper() { delete ptr_; }
|
||||
T* get() const { return ptr_; }
|
||||
OwnedWrapper(const OwnedWrapper& other) {
|
||||
ptr_ = other.ptr_;
|
||||
other.ptr_ = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable T* ptr_;
|
||||
};
|
||||
|
||||
// PassedWrapper is a copyable adapter for a scoper that ignores const.
|
||||
//
|
||||
// It is needed to get around the fact that Bind() takes a const reference to
|
||||
// all its arguments. Because Bind() takes a const reference to avoid
|
||||
// unnecessary copies, it is incompatible with movable-but-not-copyable
|
||||
// types; doing a destructive "move" of the type into Bind() would violate
|
||||
// the const correctness.
|
||||
//
|
||||
// This conundrum cannot be solved without either C++11 rvalue references or
|
||||
// a O(2^n) blowup of Bind() templates to handle each combination of regular
|
||||
// types and movable-but-not-copyable types. Thus we introduce a wrapper type
|
||||
// that is copyable to transmit the correct type information down into
|
||||
// BindState<>. Ignoring const in this type makes sense because it is only
|
||||
// created when we are explicitly trying to do a destructive move.
|
||||
//
|
||||
// Two notes:
|
||||
// 1) PassedWrapper supports any type that has a "Pass()" function.
|
||||
// This is intentional. The whitelisting of which specific types we
|
||||
// support is maintained by CallbackParamTraits<>.
|
||||
// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
|
||||
// scoper to a Callback and allow the Callback to execute once.
|
||||
template <typename T>
|
||||
class PassedWrapper {
|
||||
public:
|
||||
explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
|
||||
PassedWrapper(const PassedWrapper& other)
|
||||
: is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {
|
||||
}
|
||||
T Pass() const {
|
||||
CHECK(is_valid_);
|
||||
is_valid_ = false;
|
||||
return scoper_.Pass();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable bool is_valid_;
|
||||
mutable T scoper_;
|
||||
};
|
||||
|
||||
// Unwrap the stored parameters for the wrappers above.
|
||||
template <typename T>
|
||||
struct UnwrapTraits {
|
||||
typedef const T& ForwardType;
|
||||
static ForwardType Unwrap(const T& o) { return o; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<UnretainedWrapper<T> > {
|
||||
typedef T* ForwardType;
|
||||
static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
|
||||
return unretained.get();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<ConstRefWrapper<T> > {
|
||||
typedef const T& ForwardType;
|
||||
static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
|
||||
return const_ref.get();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<scoped_refptr<T> > {
|
||||
typedef T* ForwardType;
|
||||
static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<WeakPtr<T> > {
|
||||
typedef const WeakPtr<T>& ForwardType;
|
||||
static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<OwnedWrapper<T> > {
|
||||
typedef T* ForwardType;
|
||||
static ForwardType Unwrap(const OwnedWrapper<T>& o) {
|
||||
return o.get();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapTraits<PassedWrapper<T> > {
|
||||
typedef T ForwardType;
|
||||
static T Unwrap(PassedWrapper<T>& o) {
|
||||
return o.Pass();
|
||||
}
|
||||
};
|
||||
|
||||
// Utility for handling different refcounting semantics in the Bind()
|
||||
// function.
|
||||
template <bool is_method, typename T>
|
||||
struct MaybeRefcount;
|
||||
|
||||
template <typename T>
|
||||
struct MaybeRefcount<false, T> {
|
||||
static void AddRef(const T&) {}
|
||||
static void Release(const T&) {}
|
||||
};
|
||||
|
||||
template <typename T, size_t n>
|
||||
struct MaybeRefcount<false, T[n]> {
|
||||
static void AddRef(const T*) {}
|
||||
static void Release(const T*) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MaybeRefcount<true, T> {
|
||||
static void AddRef(const T&) {}
|
||||
static void Release(const T&) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MaybeRefcount<true, T*> {
|
||||
static void AddRef(T* o) { o->AddRef(); }
|
||||
static void Release(T* o) { o->Release(); }
|
||||
};
|
||||
|
||||
// No need to additionally AddRef() and Release() since we are storing a
|
||||
// scoped_refptr<> inside the storage object already.
|
||||
template <typename T>
|
||||
struct MaybeRefcount<true, scoped_refptr<T> > {
|
||||
static void AddRef(const scoped_refptr<T>& o) {}
|
||||
static void Release(const scoped_refptr<T>& o) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MaybeRefcount<true, const T*> {
|
||||
static void AddRef(const T* o) { o->AddRef(); }
|
||||
static void Release(const T* o) { o->Release(); }
|
||||
};
|
||||
|
||||
// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
|
||||
// method. It is used internally by Bind() to select the correct
|
||||
// InvokeHelper that will no-op itself in the event the WeakPtr<> for
|
||||
// the target object is invalidated.
|
||||
//
|
||||
// P1 should be the type of the object that will be received of the method.
|
||||
template <bool IsMethod, typename P1>
|
||||
struct IsWeakMethod : public false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
|
||||
|
||||
template <typename T>
|
||||
struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
template <typename T>
|
||||
static inline cef_internal::UnretainedWrapper<T> Unretained(T* o) {
|
||||
return cef_internal::UnretainedWrapper<T>(o);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline cef_internal::ConstRefWrapper<T> ConstRef(const T& o) {
|
||||
return cef_internal::ConstRefWrapper<T>(o);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline cef_internal::OwnedWrapper<T> Owned(T* o) {
|
||||
return cef_internal::OwnedWrapper<T>(o);
|
||||
}
|
||||
|
||||
// We offer 2 syntaxes for calling Passed(). The first takes a temporary and
|
||||
// is best suited for use with the return value of a function. The second
|
||||
// takes a pointer to the scoper and is just syntactic sugar to avoid having
|
||||
// to write Passed(scoper.Pass()).
|
||||
template <typename T>
|
||||
static inline cef_internal::PassedWrapper<T> Passed(T scoper) {
|
||||
return cef_internal::PassedWrapper<T>(scoper.Pass());
|
||||
}
|
||||
template <typename T>
|
||||
static inline cef_internal::PassedWrapper<T> Passed(T* scoper) {
|
||||
return cef_internal::PassedWrapper<T>(scoper->Pass());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline cef_internal::IgnoreResultHelper<T> IgnoreResult(T data) {
|
||||
return cef_internal::IgnoreResultHelper<T>(data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline cef_internal::IgnoreResultHelper<Callback<T> >
|
||||
IgnoreResult(const Callback<T>& data) {
|
||||
return cef_internal::IgnoreResultHelper<Callback<T> >(data);
|
||||
}
|
||||
|
||||
void DoNothing();
|
||||
|
||||
template<typename T>
|
||||
void DeletePointer(T* obj) {
|
||||
delete obj;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
|
186
include/base/cef_build.h
Normal file
186
include/base/cef_build.h
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_BUILD_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/compiler_specific.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef OS_WIN
|
||||
#define OS_WIN 1
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#ifndef OS_MACOSX
|
||||
#define OS_MACOSX 1
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#ifndef OS_LINUX
|
||||
#define OS_LINUX 1
|
||||
#endif
|
||||
#else
|
||||
#error Please add support for your platform in cef_build.h
|
||||
#endif
|
||||
|
||||
// For access to standard POSIXish features, use OS_POSIX instead of a
|
||||
// more specific macro.
|
||||
#if defined(OS_MACOSX) || defined(OS_LINUX)
|
||||
#ifndef OS_POSIX
|
||||
#define OS_POSIX 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Compiler detection.
|
||||
#if defined(__GNUC__)
|
||||
#ifndef COMPILER_GCC
|
||||
#define COMPILER_GCC 1
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#ifndef COMPILER_MSVC
|
||||
#define COMPILER_MSVC 1
|
||||
#endif
|
||||
#else
|
||||
#error Please add support for your compiler in cef_build.h
|
||||
#endif
|
||||
|
||||
// Processor architecture detection. For more info on what's defined, see:
|
||||
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// http://www.agner.org/optimize/calling_conventions.pdf
|
||||
// or with gcc, run: "echo | gcc -E -dM -"
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define ARCH_CPU_X86_FAMILY 1
|
||||
#define ARCH_CPU_X86_64 1
|
||||
#define ARCH_CPU_64_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
#define ARCH_CPU_X86_FAMILY 1
|
||||
#define ARCH_CPU_X86 1
|
||||
#define ARCH_CPU_32_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#elif defined(__ARMEL__)
|
||||
#define ARCH_CPU_ARM_FAMILY 1
|
||||
#define ARCH_CPU_ARMEL 1
|
||||
#define ARCH_CPU_32_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#elif defined(__aarch64__)
|
||||
#define ARCH_CPU_ARM_FAMILY 1
|
||||
#define ARCH_CPU_ARM64 1
|
||||
#define ARCH_CPU_64_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#elif defined(__pnacl__)
|
||||
#define ARCH_CPU_32_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#elif defined(__MIPSEL__)
|
||||
#define ARCH_CPU_MIPS_FAMILY 1
|
||||
#define ARCH_CPU_MIPSEL 1
|
||||
#define ARCH_CPU_32_BITS 1
|
||||
#define ARCH_CPU_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#error Please add support for your architecture in cef_build.h
|
||||
#endif
|
||||
|
||||
// Type detection for wchar_t.
|
||||
#if defined(OS_WIN)
|
||||
#define WCHAR_T_IS_UTF16
|
||||
#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
|
||||
defined(__WCHAR_MAX__) && \
|
||||
(__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
|
||||
#define WCHAR_T_IS_UTF32
|
||||
#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
|
||||
defined(__WCHAR_MAX__) && \
|
||||
(__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
|
||||
// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
|
||||
// compile in this mode (in particular, Chrome doesn't). This is intended for
|
||||
// other projects using base who manage their own dependencies and make sure
|
||||
// short wchar works for them.
|
||||
#define WCHAR_T_IS_UTF16
|
||||
#else
|
||||
#error Please add support for your compiler in cef_build.h
|
||||
#endif
|
||||
|
||||
// Annotate a virtual method indicating it must be overriding a virtual
|
||||
// method in the parent class.
|
||||
// Use like:
|
||||
// virtual void foo() OVERRIDE;
|
||||
#ifndef OVERRIDE
|
||||
#if defined(__clang__) || defined(COMPILER_MSVC)
|
||||
#define OVERRIDE override
|
||||
#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
|
||||
// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
|
||||
#define OVERRIDE override
|
||||
#else
|
||||
#define OVERRIDE
|
||||
#endif
|
||||
#endif // OVERRIDE
|
||||
|
||||
// Annotate a function indicating the caller must examine the return value.
|
||||
// Use like:
|
||||
// int foo() WARN_UNUSED_RESULT;
|
||||
// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
|
||||
#ifndef WARN_UNUSED_RESULT
|
||||
#if defined(COMPILER_GCC)
|
||||
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#endif // WARN_UNUSED_RESULT
|
||||
|
||||
// Annotate a typedef or function indicating it's ok if it's not used.
|
||||
// Use like:
|
||||
// typedef Foo Bar ALLOW_UNUSED_TYPE;
|
||||
#ifndef ALLOW_UNUSED_TYPE
|
||||
#if defined(COMPILER_GCC)
|
||||
#define ALLOW_UNUSED_TYPE __attribute__((unused))
|
||||
#else
|
||||
#define ALLOW_UNUSED_TYPE
|
||||
#endif
|
||||
#endif // ALLOW_UNUSED_TYPE
|
||||
|
||||
// Annotate a variable indicating it's ok if the variable is not used.
|
||||
// (Typically used to silence a compiler warning when the assignment
|
||||
// is important for some other reason.)
|
||||
// Use like:
|
||||
// int x = ...;
|
||||
// ALLOW_UNUSED_LOCAL(x);
|
||||
#ifndef ALLOW_UNUSED_LOCAL
|
||||
#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_BUILD_H_
|
807
include/base/cef_callback.h
Normal file
807
include/base/cef_callback.h
Normal file
@ -0,0 +1,807 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_CALLBACK_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/callback.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/internal/cef_callback_internal.h"
|
||||
#include "include/base/cef_callback_forward.h"
|
||||
#include "include/base/cef_template_util.h"
|
||||
|
||||
// NOTE: Header files that do not require the full definition of Callback or
|
||||
// Closure should #include "base/cef_callback_forward.h" instead of this file.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Introduction
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// The templated Callback class is a generalized function object. Together
|
||||
// with the Bind() function in bind.h, they provide a type-safe method for
|
||||
// performing partial application of functions.
|
||||
//
|
||||
// Partial application (or "currying") is the process of binding a subset of
|
||||
// a function's arguments to produce another function that takes fewer
|
||||
// arguments. This can be used to pass around a unit of delayed execution,
|
||||
// much like lexical closures are used in other languages. For example, it
|
||||
// is used in Chromium code to schedule tasks on different MessageLoops.
|
||||
//
|
||||
// A callback with no unbound input parameters (base::Callback<void(void)>)
|
||||
// is called a base::Closure. Note that this is NOT the same as what other
|
||||
// languages refer to as a closure -- it does not retain a reference to its
|
||||
// enclosing environment.
|
||||
//
|
||||
// MEMORY MANAGEMENT AND PASSING
|
||||
//
|
||||
// The Callback objects themselves should be passed by const-reference, and
|
||||
// stored by copy. They internally store their state via a refcounted class
|
||||
// and thus do not need to be deleted.
|
||||
//
|
||||
// The reason to pass via a const-reference is to avoid unnecessary
|
||||
// AddRef/Release pairs to the internal state.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Quick reference for basic stuff
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// BINDING A BARE FUNCTION
|
||||
//
|
||||
// int Return5() { return 5; }
|
||||
// base::Callback<int(void)> func_cb = base::Bind(&Return5);
|
||||
// LOG(INFO) << func_cb.Run(); // Prints 5.
|
||||
//
|
||||
// BINDING A CLASS METHOD
|
||||
//
|
||||
// The first argument to bind is the member function to call, the second is
|
||||
// the object on which to call it.
|
||||
//
|
||||
// class Ref : public base::RefCountedThreadSafe<Ref> {
|
||||
// public:
|
||||
// int Foo() { return 3; }
|
||||
// void PrintBye() { LOG(INFO) << "bye."; }
|
||||
// };
|
||||
// scoped_refptr<Ref> ref = new Ref();
|
||||
// base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref);
|
||||
// LOG(INFO) << ref_cb.Run(); // Prints out 3.
|
||||
//
|
||||
// By default the object must support RefCounted or you will get a compiler
|
||||
// error. If you're passing between threads, be sure it's
|
||||
// RefCountedThreadSafe! See "Advanced binding of member functions" below if
|
||||
// you don't want to use reference counting.
|
||||
//
|
||||
// RUNNING A CALLBACK
|
||||
//
|
||||
// Callbacks can be run with their "Run" method, which has the same
|
||||
// signature as the template argument to the callback.
|
||||
//
|
||||
// void DoSomething(const base::Callback<void(int, std::string)>& callback) {
|
||||
// callback.Run(5, "hello");
|
||||
// }
|
||||
//
|
||||
// Callbacks can be run more than once (they don't get deleted or marked when
|
||||
// run). However, this precludes using base::Passed (see below).
|
||||
//
|
||||
// void DoSomething(const base::Callback<double(double)>& callback) {
|
||||
// double myresult = callback.Run(3.14159);
|
||||
// myresult += callback.Run(2.71828);
|
||||
// }
|
||||
//
|
||||
// PASSING UNBOUND INPUT PARAMETERS
|
||||
//
|
||||
// Unbound parameters are specified at the time a callback is Run(). They are
|
||||
// specified in the Callback template type:
|
||||
//
|
||||
// void MyFunc(int i, const std::string& str) {}
|
||||
// base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc);
|
||||
// cb.Run(23, "hello, world");
|
||||
//
|
||||
// PASSING BOUND INPUT PARAMETERS
|
||||
//
|
||||
// Bound parameters are specified when you create thee callback as arguments
|
||||
// to Bind(). They will be passed to the function and the Run()ner of the
|
||||
// callback doesn't see those values or even know that the function it's
|
||||
// calling.
|
||||
//
|
||||
// void MyFunc(int i, const std::string& str) {}
|
||||
// base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world");
|
||||
// cb.Run();
|
||||
//
|
||||
// A callback with no unbound input parameters (base::Callback<void(void)>)
|
||||
// is called a base::Closure. So we could have also written:
|
||||
//
|
||||
// base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
|
||||
//
|
||||
// When calling member functions, bound parameters just go after the object
|
||||
// pointer.
|
||||
//
|
||||
// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
|
||||
//
|
||||
// PARTIAL BINDING OF PARAMETERS
|
||||
//
|
||||
// You can specify some parameters when you create the callback, and specify
|
||||
// the rest when you execute the callback.
|
||||
//
|
||||
// void MyFunc(int i, const std::string& str) {}
|
||||
// base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23);
|
||||
// cb.Run("hello world");
|
||||
//
|
||||
// When calling a function bound parameters are first, followed by unbound
|
||||
// parameters.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Quick reference for advanced binding
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// BINDING A CLASS METHOD WITH WEAK POINTERS
|
||||
//
|
||||
// base::Bind(&MyClass::Foo, GetWeakPtr());
|
||||
//
|
||||
// The callback will not be run if the object has already been destroyed.
|
||||
// DANGER: weak pointers are not threadsafe, so don't use this
|
||||
// when passing between threads!
|
||||
//
|
||||
// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT
|
||||
//
|
||||
// base::Bind(&MyClass::Foo, base::Unretained(this));
|
||||
//
|
||||
// This disables all lifetime management on the object. You're responsible
|
||||
// for making sure the object is alive at the time of the call. You break it,
|
||||
// you own it!
|
||||
//
|
||||
// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS
|
||||
//
|
||||
// MyClass* myclass = new MyClass;
|
||||
// base::Bind(&MyClass::Foo, base::Owned(myclass));
|
||||
//
|
||||
// The object will be deleted when the callback is destroyed, even if it's
|
||||
// not run (like if you post a task during shutdown). Potentially useful for
|
||||
// "fire and forget" cases.
|
||||
//
|
||||
// IGNORING RETURN VALUES
|
||||
//
|
||||
// Sometimes you want to call a function that returns a value in a callback
|
||||
// that doesn't expect a return value.
|
||||
//
|
||||
// int DoSomething(int arg) { cout << arg << endl; }
|
||||
// base::Callback<void<int>) cb =
|
||||
// base::Bind(base::IgnoreResult(&DoSomething));
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Quick reference for binding parameters to Bind()
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Bound parameters are specified as arguments to Bind() and are passed to the
|
||||
// function. A callback with no parameters or no unbound parameters is called a
|
||||
// Closure (base::Callback<void(void)> and base::Closure are the same thing).
|
||||
//
|
||||
// PASSING PARAMETERS OWNED BY THE CALLBACK
|
||||
//
|
||||
// void Foo(int* arg) { cout << *arg << endl; }
|
||||
// int* pn = new int(1);
|
||||
// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
|
||||
//
|
||||
// The parameter will be deleted when the callback is destroyed, even if it's
|
||||
// not run (like if you post a task during shutdown).
|
||||
//
|
||||
// PASSING PARAMETERS AS A scoped_ptr
|
||||
//
|
||||
// void TakesOwnership(scoped_ptr<Foo> arg) {}
|
||||
// scoped_ptr<Foo> f(new Foo);
|
||||
// // f becomes null during the following call.
|
||||
// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
|
||||
//
|
||||
// Ownership of the parameter will be with the callback until the it is run,
|
||||
// when ownership is passed to the callback function. This means the callback
|
||||
// can only be run once. If the callback is never run, it will delete the
|
||||
// object when it's destroyed.
|
||||
//
|
||||
// PASSING PARAMETERS AS A scoped_refptr
|
||||
//
|
||||
// void TakesOneRef(scoped_refptr<Foo> arg) {}
|
||||
// scoped_refptr<Foo> f(new Foo)
|
||||
// base::Closure cb = base::Bind(&TakesOneRef, f);
|
||||
//
|
||||
// This should "just work." The closure will take a reference as long as it
|
||||
// is alive, and another reference will be taken for the called function.
|
||||
//
|
||||
// PASSING PARAMETERS BY REFERENCE
|
||||
//
|
||||
// Const references are *copied* unless ConstRef is used. Example:
|
||||
//
|
||||
// void foo(const int& arg) { printf("%d %p\n", arg, &arg); }
|
||||
// int n = 1;
|
||||
// base::Closure has_copy = base::Bind(&foo, n);
|
||||
// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n));
|
||||
// n = 2;
|
||||
// foo(n); // Prints "2 0xaaaaaaaaaaaa"
|
||||
// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb"
|
||||
// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa"
|
||||
//
|
||||
// Normally parameters are copied in the closure. DANGER: ConstRef stores a
|
||||
// const reference instead, referencing the original parameter. This means
|
||||
// that you must ensure the object outlives the callback!
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation notes
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// WHERE IS THIS DESIGN FROM:
|
||||
//
|
||||
// The design Callback and Bind is heavily influenced by C++'s
|
||||
// tr1::function/tr1::bind, and by the "Google Callback" system used inside
|
||||
// Google.
|
||||
//
|
||||
//
|
||||
// HOW THE IMPLEMENTATION WORKS:
|
||||
//
|
||||
// There are three main components to the system:
|
||||
// 1) The Callback classes.
|
||||
// 2) The Bind() functions.
|
||||
// 3) The arguments wrappers (e.g., Unretained() and ConstRef()).
|
||||
//
|
||||
// The Callback classes represent a generic function pointer. Internally,
|
||||
// it stores a refcounted piece of state that represents the target function
|
||||
// and all its bound parameters. Each Callback specialization has a templated
|
||||
// constructor that takes an BindState<>*. In the context of the constructor,
|
||||
// the static type of this BindState<> pointer uniquely identifies the
|
||||
// function it is representing, all its bound parameters, and a Run() method
|
||||
// that is capable of invoking the target.
|
||||
//
|
||||
// Callback's constructor takes the BindState<>* that has the full static type
|
||||
// and erases the target function type as well as the types of the bound
|
||||
// parameters. It does this by storing a pointer to the specific Run()
|
||||
// function, and upcasting the state of BindState<>* to a
|
||||
// BindStateBase*. This is safe as long as this BindStateBase pointer
|
||||
// is only used with the stored Run() pointer.
|
||||
//
|
||||
// To BindState<> objects are created inside the Bind() functions.
|
||||
// These functions, along with a set of internal templates, are responsible for
|
||||
//
|
||||
// - Unwrapping the function signature into return type, and parameters
|
||||
// - Determining the number of parameters that are bound
|
||||
// - Creating the BindState storing the bound parameters
|
||||
// - Performing compile-time asserts to avoid error-prone behavior
|
||||
// - Returning an Callback<> with an arity matching the number of unbound
|
||||
// parameters and that knows the correct refcounting semantics for the
|
||||
// target object if we are binding a method.
|
||||
//
|
||||
// The Bind functions do the above using type-inference, and template
|
||||
// specializations.
|
||||
//
|
||||
// By default Bind() will store copies of all bound parameters, and attempt
|
||||
// to refcount a target object if the function being bound is a class method.
|
||||
// These copies are created even if the function takes parameters as const
|
||||
// references. (Binding to non-const references is forbidden, see bind.h.)
|
||||
//
|
||||
// To change this behavior, we introduce a set of argument wrappers
|
||||
// (e.g., Unretained(), and ConstRef()). These are simple container templates
|
||||
// that are passed by value, and wrap a pointer to argument. See the
|
||||
// file-level comment in base/bind_helpers.h for more info.
|
||||
//
|
||||
// These types are passed to the Unwrap() functions, and the MaybeRefcount()
|
||||
// functions respectively to modify the behavior of Bind(). The Unwrap()
|
||||
// and MaybeRefcount() functions change behavior by doing partial
|
||||
// specialization based on whether or not a parameter is a wrapper type.
|
||||
//
|
||||
// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium.
|
||||
//
|
||||
//
|
||||
// WHY NOT TR1 FUNCTION/BIND?
|
||||
//
|
||||
// Direct use of tr1::function and tr1::bind was considered, but ultimately
|
||||
// rejected because of the number of copy constructors invocations involved
|
||||
// in the binding of arguments during construction, and the forwarding of
|
||||
// arguments during invocation. These copies will no longer be an issue in
|
||||
// C++0x because C++0x will support rvalue reference allowing for the compiler
|
||||
// to avoid these copies. However, waiting for C++0x is not an option.
|
||||
//
|
||||
// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
|
||||
// tr1::bind call itself will invoke a non-trivial copy constructor three times
|
||||
// for each bound parameter. Also, each when passing a tr1::function, each
|
||||
// bound argument will be copied again.
|
||||
//
|
||||
// In addition to the copies taken at binding and invocation, copying a
|
||||
// tr1::function causes a copy to be made of all the bound parameters and
|
||||
// state.
|
||||
//
|
||||
// Furthermore, in Chromium, it is desirable for the Callback to take a
|
||||
// reference on a target object when representing a class method call. This
|
||||
// is not supported by tr1.
|
||||
//
|
||||
// Lastly, tr1::function and tr1::bind has a more general and flexible API.
|
||||
// This includes things like argument reordering by use of
|
||||
// tr1::bind::placeholder, support for non-const reference parameters, and some
|
||||
// limited amount of subtyping of the tr1::function object (e.g.,
|
||||
// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
|
||||
//
|
||||
// These are not features that are required in Chromium. Some of them, such as
|
||||
// allowing for reference parameters, and subtyping of functions, may actually
|
||||
// become a source of errors. Removing support for these features actually
|
||||
// allows for a simpler implementation, and a terser Currying API.
|
||||
//
|
||||
//
|
||||
// WHY NOT GOOGLE CALLBACKS?
|
||||
//
|
||||
// The Google callback system also does not support refcounting. Furthermore,
|
||||
// its implementation has a number of strange edge cases with respect to type
|
||||
// conversion of its arguments. In particular, the argument's constness must
|
||||
// at times match exactly the function signature, or the type-inference might
|
||||
// break. Given the above, writing a custom solution was easier.
|
||||
//
|
||||
//
|
||||
// MISSING FUNCTIONALITY
|
||||
// - Invoking the return of Bind. Bind(&foo).Run() does not work;
|
||||
// - Binding arrays to functions that take a non-const pointer.
|
||||
// Example:
|
||||
// void Foo(const char* ptr);
|
||||
// void Bar(char* ptr);
|
||||
// Bind(&Foo, "test");
|
||||
// Bind(&Bar, "test"); // This fails because ptr is not const.
|
||||
|
||||
namespace base {
|
||||
|
||||
// First, we forward declare the Callback class template. This informs the
|
||||
// compiler that the template only has 1 type parameter which is the function
|
||||
// signature that the Callback is representing.
|
||||
//
|
||||
// After this, create template specializations for 0-7 parameters. Note that
|
||||
// even though the template typelist grows, the specialization still
|
||||
// only has one type: the function signature.
|
||||
//
|
||||
// If you are thinking of forward declaring Callback in your own header file,
|
||||
// please include "base/callback_forward.h" instead.
|
||||
template <typename Sig>
|
||||
class Callback;
|
||||
|
||||
namespace cef_internal {
|
||||
template <typename Runnable, typename RunType, typename BoundArgsType>
|
||||
struct BindState;
|
||||
} // namespace cef_internal
|
||||
|
||||
template <typename R>
|
||||
class Callback<R(void)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)();
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run() const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get());
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1>
|
||||
class Callback<R(A1)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2>
|
||||
class Callback<R(A1, A2)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3>
|
||||
class Callback<R(A1, A2, A3)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2, A3);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2),
|
||||
cef_internal::CallbackForward(a3));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||
class Callback<R(A1, A2, A3, A4)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2, A3, A4);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2),
|
||||
cef_internal::CallbackForward(a3),
|
||||
cef_internal::CallbackForward(a4));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5>
|
||||
class Callback<R(A1, A2, A3, A4, A5)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2, A3, A4, A5);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2),
|
||||
cef_internal::CallbackForward(a3),
|
||||
cef_internal::CallbackForward(a4),
|
||||
cef_internal::CallbackForward(a5));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6>
|
||||
class Callback<R(A1, A2, A3, A4, A5, A6)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2, A3, A4, A5, A6);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType a6) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2),
|
||||
cef_internal::CallbackForward(a3),
|
||||
cef_internal::CallbackForward(a4),
|
||||
cef_internal::CallbackForward(a5),
|
||||
cef_internal::CallbackForward(a6));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6, typename A7>
|
||||
class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public cef_internal::CallbackBase {
|
||||
public:
|
||||
typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
|
||||
|
||||
Callback() : CallbackBase(NULL) { }
|
||||
|
||||
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
|
||||
// return the exact Callback<> type. See base/bind.h for details.
|
||||
template <typename Runnable, typename BindRunType, typename BoundArgsType>
|
||||
Callback(cef_internal::BindState<Runnable, BindRunType,
|
||||
BoundArgsType>* bind_state)
|
||||
: CallbackBase(bind_state) {
|
||||
|
||||
// Force the assignment to a local variable of PolymorphicInvoke
|
||||
// so the compiler will typecheck that the passed in Run() method has
|
||||
// the correct type.
|
||||
PolymorphicInvoke invoke_func =
|
||||
&cef_internal::BindState<Runnable, BindRunType, BoundArgsType>
|
||||
::InvokerType::Run;
|
||||
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
||||
}
|
||||
|
||||
bool Equals(const Callback& other) const {
|
||||
return CallbackBase::Equals(other);
|
||||
}
|
||||
|
||||
R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType a6,
|
||||
typename cef_internal::CallbackParamTraits<A7>::ForwardType a7) const {
|
||||
PolymorphicInvoke f =
|
||||
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
|
||||
|
||||
return f(bind_state_.get(), cef_internal::CallbackForward(a1),
|
||||
cef_internal::CallbackForward(a2),
|
||||
cef_internal::CallbackForward(a3),
|
||||
cef_internal::CallbackForward(a4),
|
||||
cef_internal::CallbackForward(a5),
|
||||
cef_internal::CallbackForward(a6),
|
||||
cef_internal::CallbackForward(a7));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef R(*PolymorphicInvoke)(
|
||||
cef_internal::BindStateBase*,
|
||||
typename cef_internal::CallbackParamTraits<A1>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType,
|
||||
typename cef_internal::CallbackParamTraits<A7>::ForwardType);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
|
||||
// will be used in a lot of APIs with delayed execution.
|
||||
typedef Callback<void(void)> Closure;
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_H_
|
59
include/base/cef_callback_forward.h
Normal file
59
include/base/cef_callback_forward.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
|
||||
#define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_CALLBACK_FORWARD_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/callback_forward.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Sig>
|
||||
class Callback;
|
||||
|
||||
typedef Callback<void(void)> Closure;
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !!BUILDING_CEF_SHARED
|
||||
|
||||
#endif // INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
|
93
include/base/cef_callback_helpers.h
Normal file
93
include/base/cef_callback_helpers.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This defines helpful methods for dealing with Callbacks. Because Callbacks
|
||||
// are implemented using templates, with a class per callback signature, adding
|
||||
// methods to Callback<> itself is unattractive (lots of extra code gets
|
||||
// generated). Instead, consider adding methods here.
|
||||
//
|
||||
// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a
|
||||
// copy) after the original callback is Reset(). This can be handy if Run()
|
||||
// reads/writes the variable holding the Callback.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_CALLBACK_HELPERS_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/callback_helpers.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Sig>
|
||||
base::Callback<Sig> ResetAndReturn(base::Callback<Sig>* cb) {
|
||||
base::Callback<Sig> ret(*cb);
|
||||
cb->Reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ScopedClosureRunner is akin to scoped_ptr for Closures. It ensures that the
|
||||
// Closure is executed and deleted no matter how the current scope exits.
|
||||
class ScopedClosureRunner {
|
||||
public:
|
||||
ScopedClosureRunner();
|
||||
explicit ScopedClosureRunner(const Closure& closure);
|
||||
~ScopedClosureRunner();
|
||||
|
||||
void Reset();
|
||||
void Reset(const Closure& closure);
|
||||
Closure Release() WARN_UNUSED_RESULT;
|
||||
|
||||
private:
|
||||
Closure closure_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
|
444
include/base/cef_callback_list.h
Normal file
444
include/base/cef_callback_list.h
Normal file
@ -0,0 +1,444 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_CALLBACK_LIST_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/callback_list.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/internal/cef_callback_internal.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
|
||||
// OVERVIEW:
|
||||
//
|
||||
// A container for a list of callbacks. Unlike a normal STL vector or list,
|
||||
// this container can be modified during iteration without invalidating the
|
||||
// iterator. It safely handles the case of a callback removing itself
|
||||
// or another callback from the list while callbacks are being run.
|
||||
//
|
||||
// TYPICAL USAGE:
|
||||
//
|
||||
// class MyWidget {
|
||||
// public:
|
||||
// ...
|
||||
//
|
||||
// typedef base::Callback<void(const Foo&)> OnFooCallback;
|
||||
//
|
||||
// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
|
||||
// RegisterCallback(const OnFooCallback& cb) {
|
||||
// return callback_list_.Add(cb);
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// void NotifyFoo(const Foo& foo) {
|
||||
// callback_list_.Notify(foo);
|
||||
// }
|
||||
//
|
||||
// base::CallbackList<void(const Foo&)> callback_list_;
|
||||
//
|
||||
// DISALLOW_COPY_AND_ASSIGN(MyWidget);
|
||||
// };
|
||||
//
|
||||
//
|
||||
// class MyWidgetListener {
|
||||
// public:
|
||||
// MyWidgetListener::MyWidgetListener() {
|
||||
// foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
|
||||
// base::Bind(&MyWidgetListener::OnFoo, this)));
|
||||
// }
|
||||
//
|
||||
// MyWidgetListener::~MyWidgetListener() {
|
||||
// // Subscription gets deleted automatically and will deregister
|
||||
// // the callback in the process.
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// void OnFoo(const Foo& foo) {
|
||||
// // Do something.
|
||||
// }
|
||||
//
|
||||
// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
|
||||
// foo_subscription_;
|
||||
//
|
||||
// DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
|
||||
// };
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace cef_internal {
|
||||
|
||||
template <typename CallbackType>
|
||||
class CallbackListBase {
|
||||
public:
|
||||
class Subscription {
|
||||
public:
|
||||
Subscription(CallbackListBase<CallbackType>* list,
|
||||
typename std::list<CallbackType>::iterator iter)
|
||||
: list_(list),
|
||||
iter_(iter) {
|
||||
}
|
||||
|
||||
~Subscription() {
|
||||
if (list_->active_iterator_count_) {
|
||||
iter_->Reset();
|
||||
} else {
|
||||
list_->callbacks_.erase(iter_);
|
||||
if (!list_->removal_callback_.is_null())
|
||||
list_->removal_callback_.Run();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CallbackListBase<CallbackType>* list_;
|
||||
typename std::list<CallbackType>::iterator iter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Subscription);
|
||||
};
|
||||
|
||||
// Add a callback to the list. The callback will remain registered until the
|
||||
// returned Subscription is destroyed, which must occur before the
|
||||
// CallbackList is destroyed.
|
||||
scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
|
||||
DCHECK(!cb.is_null());
|
||||
return scoped_ptr<Subscription>(
|
||||
new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
|
||||
}
|
||||
|
||||
// Sets a callback which will be run when a subscription list is changed.
|
||||
void set_removal_callback(const Closure& callback) {
|
||||
removal_callback_ = callback;
|
||||
}
|
||||
|
||||
// Returns true if there are no subscriptions. This is only valid to call when
|
||||
// not looping through the list.
|
||||
bool empty() {
|
||||
DCHECK_EQ(0, active_iterator_count_);
|
||||
return callbacks_.empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
// An iterator class that can be used to access the list of callbacks.
|
||||
class Iterator {
|
||||
public:
|
||||
explicit Iterator(CallbackListBase<CallbackType>* list)
|
||||
: list_(list),
|
||||
list_iter_(list_->callbacks_.begin()) {
|
||||
++list_->active_iterator_count_;
|
||||
}
|
||||
|
||||
Iterator(const Iterator& iter)
|
||||
: list_(iter.list_),
|
||||
list_iter_(iter.list_iter_) {
|
||||
++list_->active_iterator_count_;
|
||||
}
|
||||
|
||||
~Iterator() {
|
||||
if (list_ && --list_->active_iterator_count_ == 0) {
|
||||
list_->Compact();
|
||||
}
|
||||
}
|
||||
|
||||
CallbackType* GetNext() {
|
||||
while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
|
||||
++list_iter_;
|
||||
|
||||
CallbackType* cb = NULL;
|
||||
if (list_iter_ != list_->callbacks_.end()) {
|
||||
cb = &(*list_iter_);
|
||||
++list_iter_;
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
private:
|
||||
CallbackListBase<CallbackType>* list_;
|
||||
typename std::list<CallbackType>::iterator list_iter_;
|
||||
};
|
||||
|
||||
CallbackListBase() : active_iterator_count_(0) {}
|
||||
|
||||
~CallbackListBase() {
|
||||
DCHECK_EQ(0, active_iterator_count_);
|
||||
DCHECK_EQ(0U, callbacks_.size());
|
||||
}
|
||||
|
||||
// Returns an instance of a CallbackListBase::Iterator which can be used
|
||||
// to run callbacks.
|
||||
Iterator GetIterator() {
|
||||
return Iterator(this);
|
||||
}
|
||||
|
||||
// Compact the list: remove any entries which were NULLed out during
|
||||
// iteration.
|
||||
void Compact() {
|
||||
typename std::list<CallbackType>::iterator it = callbacks_.begin();
|
||||
bool updated = false;
|
||||
while (it != callbacks_.end()) {
|
||||
if ((*it).is_null()) {
|
||||
updated = true;
|
||||
it = callbacks_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
|
||||
if (updated && !removal_callback_.is_null())
|
||||
removal_callback_.Run();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<CallbackType> callbacks_;
|
||||
int active_iterator_count_;
|
||||
Closure removal_callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
template <typename Sig> class CallbackList;
|
||||
|
||||
template <>
|
||||
class CallbackList<void(void)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(void)> > {
|
||||
public:
|
||||
typedef Callback<void(void)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify() {
|
||||
cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1>
|
||||
class CallbackList<void(A1)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1)> > {
|
||||
public:
|
||||
typedef Callback<void(A1)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2>
|
||||
class CallbackList<void(A1, A2)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2, typename A3>
|
||||
class CallbackList<void(A1, A2, A3)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2, A3)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2, A3)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2, a3);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2, typename A3, typename A4>
|
||||
class CallbackList<void(A1, A2, A3, A4)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2, A3, A4)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2, a3, a4);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||
class CallbackList<void(A1, A2, A3, A4, A5)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2, a3, a4, a5);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||
typename A6>
|
||||
class CallbackList<void(A1, A2, A3, A4, A5, A6)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5,
|
||||
A6)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType a6) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||
typename A6, typename A7>
|
||||
class CallbackList<void(A1, A2, A3, A4, A5, A6, A7)>
|
||||
: public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5, A6,
|
||||
A7)> > {
|
||||
public:
|
||||
typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
|
||||
|
||||
CallbackList() {}
|
||||
|
||||
void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename cef_internal::CallbackParamTraits<A6>::ForwardType a6,
|
||||
typename cef_internal::CallbackParamTraits<A7>::ForwardType a7) {
|
||||
typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
|
||||
this->GetIterator();
|
||||
CallbackType* cb;
|
||||
while ((cb = it.GetNext()) != NULL) {
|
||||
cb->Run(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallbackList);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
|
314
include/base/cef_cancelable_callback.h
Normal file
314
include/base/cef_cancelable_callback.h
Normal file
@ -0,0 +1,314 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// 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
|
||||
// wrapped callback until this object is destroyed or Reset()/Cancel() are
|
||||
// called.
|
||||
//
|
||||
// NOTE:
|
||||
//
|
||||
// Calling CancelableCallback::Cancel() brings the object back to its natural,
|
||||
// default-constructed state, i.e., CancelableCallback::callback() will return
|
||||
// a null callback.
|
||||
//
|
||||
// THREAD-SAFETY:
|
||||
//
|
||||
// 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()
|
||||
// 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,
|
||||
// then the callback is cancelled.
|
||||
//
|
||||
// void TimeoutCallback(const std::string& timeout_message) {
|
||||
// FAIL() << timeout_message;
|
||||
// MessageLoop::current()->QuitWhenIdle();
|
||||
// }
|
||||
//
|
||||
// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out."));
|
||||
// MessageLoop::current()->PostDelayedTask(FROM_HERE, timeout.callback(),
|
||||
// 4000) // 4 seconds to run.
|
||||
// RunIntensiveTest();
|
||||
// MessageLoop::current()->Run();
|
||||
// timeout.Cancel(); // Hopefully this is hit before the timeout callback runs.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_CANCELABLE_CALLBACK_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/cancelable_callback.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_weak_ptr.h"
|
||||
#include "include/base/internal/cef_callback_internal.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Sig>
|
||||
class CancelableCallback;
|
||||
|
||||
template <>
|
||||
class CancelableCallback<void(void)> {
|
||||
public:
|
||||
CancelableCallback() : weak_factory_(this) {}
|
||||
|
||||
// |callback| must not be null.
|
||||
explicit CancelableCallback(const base::Callback<void(void)>& callback)
|
||||
: weak_factory_(this),
|
||||
callback_(callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
InitializeForwarder();
|
||||
}
|
||||
|
||||
~CancelableCallback() {}
|
||||
|
||||
// Cancels and drops the reference to the wrapped callback.
|
||||
void Cancel() {
|
||||
weak_factory_.InvalidateWeakPtrs();
|
||||
forwarder_.Reset();
|
||||
callback_.Reset();
|
||||
}
|
||||
|
||||
// Returns true if the wrapped callback has been cancelled.
|
||||
bool IsCancelled() const {
|
||||
return callback_.is_null();
|
||||
}
|
||||
|
||||
// Sets |callback| as the closure that may be cancelled. |callback| may not
|
||||
// be null. Outstanding and any previously wrapped callbacks are cancelled.
|
||||
void Reset(const base::Callback<void(void)>& callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
|
||||
// Outstanding tasks (e.g., posted to a message loop) must not be called.
|
||||
Cancel();
|
||||
|
||||
// |forwarder_| is no longer valid after Cancel(), so re-bind.
|
||||
InitializeForwarder();
|
||||
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
// Returns a callback that can be disabled by calling Cancel().
|
||||
const base::Callback<void(void)>& callback() const {
|
||||
return forwarder_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Forward() {
|
||||
callback_.Run();
|
||||
}
|
||||
|
||||
// Helper method to bind |forwarder_| using a weak pointer from
|
||||
// |weak_factory_|.
|
||||
void InitializeForwarder() {
|
||||
forwarder_ = base::Bind(&CancelableCallback<void(void)>::Forward,
|
||||
weak_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
// Used to ensure Forward() is not run when this object is destroyed.
|
||||
base::WeakPtrFactory<CancelableCallback<void(void)> > weak_factory_;
|
||||
|
||||
// The wrapper closure.
|
||||
base::Callback<void(void)> forwarder_;
|
||||
|
||||
// The stored closure that may be cancelled.
|
||||
base::Callback<void(void)> callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
|
||||
};
|
||||
|
||||
template <typename A1>
|
||||
class CancelableCallback<void(A1)> {
|
||||
public:
|
||||
CancelableCallback() : weak_factory_(this) {}
|
||||
|
||||
// |callback| must not be null.
|
||||
explicit CancelableCallback(const base::Callback<void(A1)>& callback)
|
||||
: weak_factory_(this),
|
||||
callback_(callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
InitializeForwarder();
|
||||
}
|
||||
|
||||
~CancelableCallback() {}
|
||||
|
||||
// Cancels and drops the reference to the wrapped callback.
|
||||
void Cancel() {
|
||||
weak_factory_.InvalidateWeakPtrs();
|
||||
forwarder_.Reset();
|
||||
callback_.Reset();
|
||||
}
|
||||
|
||||
// Returns true if the wrapped callback has been cancelled.
|
||||
bool IsCancelled() const {
|
||||
return callback_.is_null();
|
||||
}
|
||||
|
||||
// Sets |callback| as the closure that may be cancelled. |callback| may not
|
||||
// be null. Outstanding and any previously wrapped callbacks are cancelled.
|
||||
void Reset(const base::Callback<void(A1)>& callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
|
||||
// Outstanding tasks (e.g., posted to a message loop) must not be called.
|
||||
Cancel();
|
||||
|
||||
// |forwarder_| is no longer valid after Cancel(), so re-bind.
|
||||
InitializeForwarder();
|
||||
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
// Returns a callback that can be disabled by calling Cancel().
|
||||
const base::Callback<void(A1)>& callback() const {
|
||||
return forwarder_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Forward(A1 a1) const {
|
||||
callback_.Run(a1);
|
||||
}
|
||||
|
||||
// Helper method to bind |forwarder_| using a weak pointer from
|
||||
// |weak_factory_|.
|
||||
void InitializeForwarder() {
|
||||
forwarder_ = base::Bind(&CancelableCallback<void(A1)>::Forward,
|
||||
weak_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
// Used to ensure Forward() is not run when this object is destroyed.
|
||||
base::WeakPtrFactory<CancelableCallback<void(A1)> > weak_factory_;
|
||||
|
||||
// The wrapper closure.
|
||||
base::Callback<void(A1)> forwarder_;
|
||||
|
||||
// The stored closure that may be cancelled.
|
||||
base::Callback<void(A1)> callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
|
||||
};
|
||||
|
||||
template <typename A1, typename A2>
|
||||
class CancelableCallback<void(A1, A2)> {
|
||||
public:
|
||||
CancelableCallback() : weak_factory_(this) {}
|
||||
|
||||
// |callback| must not be null.
|
||||
explicit CancelableCallback(const base::Callback<void(A1, A2)>& callback)
|
||||
: weak_factory_(this),
|
||||
callback_(callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
InitializeForwarder();
|
||||
}
|
||||
|
||||
~CancelableCallback() {}
|
||||
|
||||
// Cancels and drops the reference to the wrapped callback.
|
||||
void Cancel() {
|
||||
weak_factory_.InvalidateWeakPtrs();
|
||||
forwarder_.Reset();
|
||||
callback_.Reset();
|
||||
}
|
||||
|
||||
// Returns true if the wrapped callback has been cancelled.
|
||||
bool IsCancelled() const {
|
||||
return callback_.is_null();
|
||||
}
|
||||
|
||||
// Sets |callback| as the closure that may be cancelled. |callback| may not
|
||||
// be null. Outstanding and any previously wrapped callbacks are cancelled.
|
||||
void Reset(const base::Callback<void(A1, A2)>& callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
|
||||
// Outstanding tasks (e.g., posted to a message loop) must not be called.
|
||||
Cancel();
|
||||
|
||||
// |forwarder_| is no longer valid after Cancel(), so re-bind.
|
||||
InitializeForwarder();
|
||||
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
// Returns a callback that can be disabled by calling Cancel().
|
||||
const base::Callback<void(A1, A2)>& callback() const {
|
||||
return forwarder_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Forward(A1 a1, A2 a2) const {
|
||||
callback_.Run(a1, a2);
|
||||
}
|
||||
|
||||
// Helper method to bind |forwarder_| using a weak pointer from
|
||||
// |weak_factory_|.
|
||||
void InitializeForwarder() {
|
||||
forwarder_ = base::Bind(&CancelableCallback<void(A1, A2)>::Forward,
|
||||
weak_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
// Used to ensure Forward() is not run when this object is destroyed.
|
||||
base::WeakPtrFactory<CancelableCallback<void(A1, A2)> > weak_factory_;
|
||||
|
||||
// The wrapper closure.
|
||||
base::Callback<void(A1, A2)> forwarder_;
|
||||
|
||||
// The stored closure that may be cancelled.
|
||||
base::Callback<void(A1, A2)> callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
|
||||
};
|
||||
|
||||
typedef CancelableCallback<void(void)> CancelableClosure;
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
|
167
include/base/cef_lock.h
Normal file
167
include/base/cef_lock.h
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_LOCK_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_LOCK_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_SYNCHRONIZATION_LOCK_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/synchronization/lock.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_platform_thread.h"
|
||||
#include "include/base/internal/cef_lock_impl.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// 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
|
||||
// AssertAcquired() method.
|
||||
class Lock {
|
||||
public:
|
||||
#if defined(NDEBUG) // Optimized wrapper implementation
|
||||
Lock() : lock_() {}
|
||||
~Lock() {}
|
||||
void Acquire() { lock_.Lock(); }
|
||||
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
|
||||
// by a thread already holding the lock (what happens is undefined and an
|
||||
// assertion may fail).
|
||||
bool Try() { return lock_.Try(); }
|
||||
|
||||
// Null implementation if not debug.
|
||||
void AssertAcquired() const {}
|
||||
#else
|
||||
Lock();
|
||||
~Lock();
|
||||
|
||||
// NOTE: Although windows critical sections support recursive locks, we do not
|
||||
// allow this, and we will commonly fire a DCHECK() if a thread attempts to
|
||||
// acquire the lock a second time (while already holding it).
|
||||
void Acquire() {
|
||||
lock_.Lock();
|
||||
CheckUnheldAndMark();
|
||||
}
|
||||
void Release() {
|
||||
CheckHeldAndUnmark();
|
||||
lock_.Unlock();
|
||||
}
|
||||
|
||||
bool Try() {
|
||||
bool rv = lock_.Try();
|
||||
if (rv) {
|
||||
CheckUnheldAndMark();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void AssertAcquired() const;
|
||||
#endif // NDEBUG
|
||||
|
||||
private:
|
||||
#if !defined(NDEBUG)
|
||||
// Members and routines taking care of locks assertions.
|
||||
// Note that this checks for recursive locks and allows them
|
||||
// if the variable is set. This is allowed by the underlying implementation
|
||||
// on windows but not on Posix, so we're doing unneeded checks on Posix.
|
||||
// It's worth it to share the code.
|
||||
void CheckHeldAndUnmark();
|
||||
void CheckUnheldAndMark();
|
||||
|
||||
// All private data is implicitly protected by lock_.
|
||||
// Be VERY careful to only access members under that lock.
|
||||
base::PlatformThreadRef owning_thread_ref_;
|
||||
#endif // NDEBUG
|
||||
|
||||
// Platform specific underlying lock implementation.
|
||||
cef_internal::LockImpl lock_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Lock);
|
||||
};
|
||||
|
||||
// A helper class that acquires the given Lock while the AutoLock is in scope.
|
||||
class AutoLock {
|
||||
public:
|
||||
struct AlreadyAcquired {};
|
||||
|
||||
explicit AutoLock(Lock& lock) : lock_(lock) {
|
||||
lock_.Acquire();
|
||||
}
|
||||
|
||||
AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) {
|
||||
lock_.AssertAcquired();
|
||||
}
|
||||
|
||||
~AutoLock() {
|
||||
lock_.AssertAcquired();
|
||||
lock_.Release();
|
||||
}
|
||||
|
||||
private:
|
||||
Lock& lock_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoLock);
|
||||
};
|
||||
|
||||
// AutoUnlock is a helper that will Release() the |lock| argument in the
|
||||
// constructor, and re-Acquire() it in the destructor.
|
||||
class AutoUnlock {
|
||||
public:
|
||||
explicit AutoUnlock(Lock& lock) : lock_(lock) {
|
||||
// We require our caller to have the lock.
|
||||
lock_.AssertAcquired();
|
||||
lock_.Release();
|
||||
}
|
||||
|
||||
~AutoUnlock() {
|
||||
lock_.Acquire();
|
||||
}
|
||||
|
||||
private:
|
||||
Lock& lock_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoUnlock);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_LOCK_H_
|
746
include/base/cef_logging.h
Normal file
746
include/base/cef_logging.h
Normal file
@ -0,0 +1,746 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// The contents of this file are only available to applications that link
|
||||
// against the libcef_dll_wrapper target.
|
||||
//
|
||||
// WARNING: Logging macros should not be used in the main/browser process before
|
||||
// calling CefInitialize or in sub-processes before calling CefExecuteProcess.
|
||||
//
|
||||
// Instructions
|
||||
// ------------
|
||||
//
|
||||
// Make a bunch of macros for logging. The way to log things is to stream
|
||||
// things to LOG(<a particular severity level>). E.g.,
|
||||
//
|
||||
// LOG(INFO) << "Found " << num_cookies << " cookies";
|
||||
//
|
||||
// You can also do conditional logging:
|
||||
//
|
||||
// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
||||
//
|
||||
// The CHECK(condition) macro is active in both debug and release builds and
|
||||
// effectively performs a LOG(FATAL) which terminates the process and
|
||||
// generates a crashdump unless a debugger is attached.
|
||||
//
|
||||
// There are also "debug mode" logging macros like the ones above:
|
||||
//
|
||||
// DLOG(INFO) << "Found cookies";
|
||||
//
|
||||
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
|
||||
//
|
||||
// All "debug mode" logging is compiled away to nothing for non-debug mode
|
||||
// compiles. LOG_IF and development flags also work well together
|
||||
// because the code can be compiled away sometimes.
|
||||
//
|
||||
// We also have
|
||||
//
|
||||
// LOG_ASSERT(assertion);
|
||||
// DLOG_ASSERT(assertion);
|
||||
//
|
||||
// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
|
||||
//
|
||||
// There are "verbose level" logging macros. They look like
|
||||
//
|
||||
// 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";
|
||||
//
|
||||
// These always log at the INFO log level (when they log at all).
|
||||
// The verbose logging can also be turned on module-by-module. For instance,
|
||||
// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
|
||||
// will cause:
|
||||
// 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}
|
||||
// c. VLOG(3) and lower messages to be printed from files prefixed with
|
||||
// "browser"
|
||||
// d. VLOG(4) and lower messages to be printed from files under a
|
||||
// "chromeos" directory.
|
||||
// e. VLOG(0) and lower messages to be printed from elsewhere
|
||||
//
|
||||
// The wildcarding functionality shown by (c) supports both '*' (match
|
||||
// 0 or more characters) and '?' (match any single character)
|
||||
// wildcards. Any pattern containing a forward or backward slash will
|
||||
// be tested against the whole pathname and not just the module.
|
||||
// E.g., "*/foo/bar/*=2" would change the logging level for all code
|
||||
// in source files under a "foo/bar" directory.
|
||||
//
|
||||
// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
|
||||
//
|
||||
// if (VLOG_IS_ON(2)) {
|
||||
// // do some logging preparation and logging
|
||||
// // that can't be accomplished with just VLOG(2) << ...;
|
||||
// }
|
||||
//
|
||||
// There is also a VLOG_IF "verbose level" condition macro for sample
|
||||
// cases, when some extra computation and preparation for logs is not
|
||||
// needed.
|
||||
//
|
||||
// VLOG_IF(1, (size > 1024))
|
||||
// << "I'm printed when size is more than 1024 and when you run the "
|
||||
// "program with --v=1 or more";
|
||||
//
|
||||
// We also override the standard 'assert' to use 'DLOG_ASSERT'.
|
||||
//
|
||||
// Lastly, there is:
|
||||
//
|
||||
// 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";
|
||||
//
|
||||
// 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_
|
||||
#define CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(DCHECK)
|
||||
// Do nothing if the macros provided by this header already exist.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/logging.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/internal/cef_logging_internal.h"
|
||||
|
||||
namespace cef {
|
||||
namespace logging {
|
||||
|
||||
// Gets the current log level.
|
||||
inline int GetMinLogLevel() {
|
||||
return cef_get_min_log_level();
|
||||
}
|
||||
|
||||
// Gets the current vlog level for the given file (usually taken from
|
||||
// __FILE__). Note that |N| is the size *with* the null terminator.
|
||||
template <size_t N>
|
||||
int GetVlogLevel(const char (&file)[N]) {
|
||||
return cef_get_vlog_level(file, N);
|
||||
}
|
||||
|
||||
typedef int LogSeverity;
|
||||
const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity
|
||||
// Note: the log severities are used to index into the array of names,
|
||||
// see log_severity_names.
|
||||
const LogSeverity LOG_INFO = 0;
|
||||
const LogSeverity LOG_WARNING = 1;
|
||||
const LogSeverity LOG_ERROR = 2;
|
||||
const LogSeverity LOG_FATAL = 3;
|
||||
const LogSeverity LOG_NUM_SEVERITIES = 4;
|
||||
|
||||
// LOG_DFATAL is LOG_FATAL in debug mode, ERROR in normal mode
|
||||
#ifdef NDEBUG
|
||||
const LogSeverity LOG_DFATAL = LOG_ERROR;
|
||||
#else
|
||||
const LogSeverity LOG_DFATAL = LOG_FATAL;
|
||||
#endif
|
||||
|
||||
// A few definitions of macros that don't generate much code. These are used
|
||||
// by LOG() and LOG_IF, etc. Since these are used all over our code, it's
|
||||
// better to have compact code for these operations.
|
||||
#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
|
||||
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_INFO , \
|
||||
##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
|
||||
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_WARNING , \
|
||||
##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
|
||||
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_ERROR , \
|
||||
##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
|
||||
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_FATAL , \
|
||||
##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
|
||||
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_DFATAL , \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define COMPACT_GOOGLE_LOG_INFO \
|
||||
COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
|
||||
#define COMPACT_GOOGLE_LOG_WARNING \
|
||||
COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
|
||||
#define COMPACT_GOOGLE_LOG_ERROR \
|
||||
COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
|
||||
#define COMPACT_GOOGLE_LOG_FATAL \
|
||||
COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
|
||||
#define COMPACT_GOOGLE_LOG_DFATAL \
|
||||
COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
|
||||
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
|
||||
// to keep using this syntax, we define this macro to do the same thing
|
||||
// as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that
|
||||
// the Windows SDK does for consistency.
|
||||
#define ERROR 0
|
||||
#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
|
||||
COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
|
||||
// Needed for LOG_IS_ON(ERROR).
|
||||
const LogSeverity LOG_0 = LOG_ERROR;
|
||||
#endif
|
||||
|
||||
// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also,
|
||||
// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will
|
||||
// always fire if they fail.
|
||||
#define LOG_IS_ON(severity) \
|
||||
((::cef::logging::LOG_ ## severity) >= ::cef::logging::GetMinLogLevel())
|
||||
|
||||
// We can't do any caching tricks with VLOG_IS_ON() like the
|
||||
// google-glog version since it requires GCC extensions. This means
|
||||
// that using the v-logging functions in conjunction with --vmodule
|
||||
// may be slow.
|
||||
#define VLOG_IS_ON(verboselevel) \
|
||||
((verboselevel) <= ::cef::logging::GetVlogLevel(__FILE__))
|
||||
|
||||
// Helper macro which avoids evaluating the arguments to a stream if
|
||||
// the condition doesn't hold.
|
||||
#define LAZY_STREAM(stream, condition) \
|
||||
!(condition) ? (void) 0 : ::cef::logging::LogMessageVoidify() & (stream)
|
||||
|
||||
// We use the preprocessor's merging operator, "##", so that, e.g.,
|
||||
// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny
|
||||
// subtle difference between ostream member streaming functions (e.g.,
|
||||
// ostream::operator<<(int) and ostream non-member streaming functions
|
||||
// (e.g., ::operator<<(ostream&, string&): it turns out that it's
|
||||
// impossible to stream something like a string directly to an unnamed
|
||||
// ostream. We employ a neat hack by calling the stream() member
|
||||
// function of LogMessage which seems to avoid the problem.
|
||||
#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
|
||||
|
||||
#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
|
||||
#define LOG_IF(severity, condition) \
|
||||
LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
|
||||
|
||||
#define SYSLOG(severity) LOG(severity)
|
||||
#define SYSLOG_IF(severity, condition) LOG_IF(severity, condition)
|
||||
|
||||
// The VLOG macros log with negative verbosities.
|
||||
#define VLOG_STREAM(verbose_level) \
|
||||
cef::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
|
||||
|
||||
#define VLOG(verbose_level) \
|
||||
LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
|
||||
|
||||
#define VLOG_IF(verbose_level, condition) \
|
||||
LAZY_STREAM(VLOG_STREAM(verbose_level), \
|
||||
VLOG_IS_ON(verbose_level) && (condition))
|
||||
|
||||
#if defined (OS_WIN)
|
||||
#define VPLOG_STREAM(verbose_level) \
|
||||
cef::logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \
|
||||
::cef::logging::GetLastSystemErrorCode()).stream()
|
||||
#elif defined(OS_POSIX)
|
||||
#define VPLOG_STREAM(verbose_level) \
|
||||
cef::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
|
||||
::cef::logging::GetLastSystemErrorCode()).stream()
|
||||
#endif
|
||||
|
||||
#define VPLOG(verbose_level) \
|
||||
LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
|
||||
|
||||
#define VPLOG_IF(verbose_level, condition) \
|
||||
LAZY_STREAM(VPLOG_STREAM(verbose_level), \
|
||||
VLOG_IS_ON(verbose_level) && (condition))
|
||||
|
||||
// TODO(akalin): Add more VLOG variants, e.g. VPLOG.
|
||||
|
||||
#define LOG_ASSERT(condition) \
|
||||
LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
|
||||
#define SYSLOG_ASSERT(condition) \
|
||||
SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#define PLOG_STREAM(severity) \
|
||||
COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
|
||||
::cef::logging::GetLastSystemErrorCode()).stream()
|
||||
#elif defined(OS_POSIX)
|
||||
#define PLOG_STREAM(severity) \
|
||||
COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \
|
||||
::cef::logging::GetLastSystemErrorCode()).stream()
|
||||
#endif
|
||||
|
||||
#define PLOG(severity) \
|
||||
LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity))
|
||||
|
||||
#define PLOG_IF(severity, condition) \
|
||||
LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
|
||||
|
||||
// The actual stream used isn't important.
|
||||
#define EAT_STREAM_PARAMETERS \
|
||||
true ? (void) 0 : ::cef::logging::LogMessageVoidify() & LOG_STREAM(FATAL)
|
||||
|
||||
// CHECK dies with a fatal error if condition is not true. It is *not*
|
||||
// controlled by NDEBUG, so the check will be executed regardless of
|
||||
// compilation mode.
|
||||
//
|
||||
// We make sure CHECK et al. always evaluates their arguments, as
|
||||
// doing CHECK(FunctionWithSideEffect()) is a common idiom.
|
||||
|
||||
#define CHECK(condition) \
|
||||
LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
|
||||
<< "Check failed: " #condition ". "
|
||||
|
||||
#define PCHECK(condition) \
|
||||
LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
|
||||
<< "Check failed: " #condition ". "
|
||||
|
||||
// Helper macro for binary operators.
|
||||
// Don't use this macro directly in your code, use CHECK_EQ et al below.
|
||||
//
|
||||
// TODO(akalin): Rewrite this so that constructs like if (...)
|
||||
// CHECK_EQ(...) else { ... } work properly.
|
||||
#define CHECK_OP(name, op, val1, val2) \
|
||||
if (std::string* _result = \
|
||||
cef::logging::Check##name##Impl((val1), (val2), \
|
||||
#val1 " " #op " " #val2)) \
|
||||
cef::logging::LogMessage(__FILE__, __LINE__, _result).stream()
|
||||
|
||||
// Build the error message string. This is separate from the "Impl"
|
||||
// function template because it is not performance critical and so can
|
||||
// be out of line, while the "Impl" code should be inline. Caller
|
||||
// takes ownership of the returned string.
|
||||
template<class t1, class t2>
|
||||
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
|
||||
std::ostringstream ss;
|
||||
ss << names << " (" << v1 << " vs. " << v2 << ")";
|
||||
std::string* msg = new std::string(ss.str());
|
||||
return msg;
|
||||
}
|
||||
|
||||
// MSVC doesn't like complex extern templates and DLLs.
|
||||
#if !defined(COMPILER_MSVC)
|
||||
// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
|
||||
// in logging.cc.
|
||||
extern template std::string* MakeCheckOpString<int, int>(
|
||||
const int&, const int&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned long, unsigned long>(
|
||||
const unsigned long&, const unsigned long&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned long, unsigned int>(
|
||||
const unsigned long&, const unsigned int&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned int, unsigned long>(
|
||||
const unsigned int&, const unsigned long&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<std::string, std::string>(
|
||||
const std::string&, const std::string&, const char* name);
|
||||
#endif
|
||||
|
||||
// Helper functions for CHECK_OP macro.
|
||||
// The (int, int) specialization works around the issue that the compiler
|
||||
// will not instantiate the template version of the function on values of
|
||||
// unnamed enum type - see comment below.
|
||||
#define DEFINE_CHECK_OP_IMPL(name, op) \
|
||||
template <class t1, class t2> \
|
||||
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
|
||||
const char* names) { \
|
||||
if (v1 op v2) return NULL; \
|
||||
else return MakeCheckOpString(v1, v2, names); \
|
||||
} \
|
||||
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
|
||||
if (v1 op v2) return NULL; \
|
||||
else return MakeCheckOpString(v1, v2, names); \
|
||||
}
|
||||
DEFINE_CHECK_OP_IMPL(EQ, ==)
|
||||
DEFINE_CHECK_OP_IMPL(NE, !=)
|
||||
DEFINE_CHECK_OP_IMPL(LE, <=)
|
||||
DEFINE_CHECK_OP_IMPL(LT, < )
|
||||
DEFINE_CHECK_OP_IMPL(GE, >=)
|
||||
DEFINE_CHECK_OP_IMPL(GT, > )
|
||||
#undef DEFINE_CHECK_OP_IMPL
|
||||
|
||||
#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
|
||||
#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
|
||||
#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
|
||||
#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
|
||||
#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
|
||||
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define ENABLE_DLOG 0
|
||||
#else
|
||||
#define ENABLE_DLOG 1
|
||||
#endif
|
||||
|
||||
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
|
||||
#define DCHECK_IS_ON 0
|
||||
#else
|
||||
#define DCHECK_IS_ON 1
|
||||
#endif
|
||||
|
||||
// Definitions for DLOG et al.
|
||||
|
||||
#if ENABLE_DLOG
|
||||
|
||||
#define DLOG_IS_ON(severity) LOG_IS_ON(severity)
|
||||
#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
|
||||
#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
|
||||
#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition)
|
||||
#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition)
|
||||
#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition)
|
||||
|
||||
#else // ENABLE_DLOG
|
||||
|
||||
// If ENABLE_DLOG is off, we want to avoid emitting any references to
|
||||
// |condition| (which may reference a variable defined only if NDEBUG
|
||||
// is not defined). Contrast this with DCHECK et al., which has
|
||||
// different behavior.
|
||||
|
||||
#define DLOG_IS_ON(severity) false
|
||||
#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
|
||||
#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS
|
||||
#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
|
||||
#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
|
||||
#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
|
||||
|
||||
#endif // ENABLE_DLOG
|
||||
|
||||
// DEBUG_MODE is for uses like
|
||||
// if (DEBUG_MODE) foo.CheckThatFoo();
|
||||
// instead of
|
||||
// #ifndef NDEBUG
|
||||
// foo.CheckThatFoo();
|
||||
// #endif
|
||||
//
|
||||
// We tie its state to ENABLE_DLOG.
|
||||
enum { DEBUG_MODE = ENABLE_DLOG };
|
||||
|
||||
#undef ENABLE_DLOG
|
||||
|
||||
#define DLOG(severity) \
|
||||
LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
|
||||
|
||||
#define DPLOG(severity) \
|
||||
LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity))
|
||||
|
||||
#define DVLOG(verboselevel) DVLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
|
||||
|
||||
#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
|
||||
|
||||
// Definitions for DCHECK et al.
|
||||
|
||||
#if DCHECK_IS_ON
|
||||
|
||||
#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
|
||||
COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL
|
||||
const LogSeverity LOG_DCHECK = LOG_FATAL;
|
||||
|
||||
#else // DCHECK_IS_ON
|
||||
|
||||
// These are just dummy values.
|
||||
#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
|
||||
COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__)
|
||||
#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO
|
||||
const LogSeverity LOG_DCHECK = LOG_INFO;
|
||||
|
||||
#endif // DCHECK_IS_ON
|
||||
|
||||
// DCHECK et al. make sure to reference |condition| regardless of
|
||||
// whether DCHECKs are enabled; this is so that we don't get unused
|
||||
// variable warnings if the only use of a variable is in a DCHECK.
|
||||
// This behavior is different from DLOG_IF et al.
|
||||
|
||||
#define DCHECK(condition) \
|
||||
LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \
|
||||
<< "Check failed: " #condition ". "
|
||||
|
||||
#define DPCHECK(condition) \
|
||||
LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \
|
||||
<< "Check failed: " #condition ". "
|
||||
|
||||
// Helper macro for binary operators.
|
||||
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
|
||||
#define DCHECK_OP(name, op, val1, val2) \
|
||||
if (DCHECK_IS_ON) \
|
||||
if (std::string* _result = \
|
||||
cef::logging::Check##name##Impl((val1), (val2), \
|
||||
#val1 " " #op " " #val2)) \
|
||||
cef::logging::LogMessage( \
|
||||
__FILE__, __LINE__, ::cef::logging::LOG_DCHECK, \
|
||||
_result).stream()
|
||||
|
||||
// Equality/Inequality checks - compare two values, and log a
|
||||
// LOG_DCHECK message including the two values when the result is not
|
||||
// as expected. The values must have operator<<(ostream, ...)
|
||||
// defined.
|
||||
//
|
||||
// You may append to the error message like so:
|
||||
// DCHECK_NE(1, 2) << ": The world must be ending!";
|
||||
//
|
||||
// We are very careful to ensure that each argument is evaluated exactly
|
||||
// once, and that anything which is legal to pass as a function argument is
|
||||
// legal here. In particular, the arguments may be temporary expressions
|
||||
// which will end up being destroyed at the end of the apparent statement,
|
||||
// for example:
|
||||
// DCHECK_EQ(string("abc")[1], 'b');
|
||||
//
|
||||
// WARNING: These may not compile correctly if one of the arguments is a pointer
|
||||
// and the other is NULL. To work around this, simply static_cast NULL to the
|
||||
// type of the desired pointer.
|
||||
|
||||
#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
|
||||
#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
|
||||
#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
|
||||
#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
|
||||
#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
|
||||
#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
|
||||
|
||||
#if defined(NDEBUG) && defined(OS_CHROMEOS)
|
||||
#define NOTREACHED() LOG(ERROR) << "NOTREACHED() hit in " << \
|
||||
__FUNCTION__ << ". "
|
||||
#else
|
||||
#define NOTREACHED() DCHECK(false)
|
||||
#endif
|
||||
|
||||
// Redefine the standard assert to use our nice log files
|
||||
#undef assert
|
||||
#define assert(x) DLOG_ASSERT(x)
|
||||
|
||||
// This class more or less represents a particular log message. You
|
||||
// create an instance of LogMessage and then stream stuff to it.
|
||||
// When you finish streaming to it, ~LogMessage is called and the
|
||||
// full message gets streamed to the appropriate destination.
|
||||
//
|
||||
// You shouldn't actually use LogMessage's constructor to log things,
|
||||
// though. You should use the LOG() macro (and variants thereof)
|
||||
// above.
|
||||
class LogMessage {
|
||||
public:
|
||||
// Used for LOG(severity).
|
||||
LogMessage(const char* file, int line, LogSeverity severity);
|
||||
|
||||
// Used for CHECK_EQ(), etc. Takes ownership of the given string.
|
||||
// Implied severity = LOG_FATAL.
|
||||
LogMessage(const char* file, int line, std::string* result);
|
||||
|
||||
// Used for DCHECK_EQ(), etc. Takes ownership of the given string.
|
||||
LogMessage(const char* file, int line, LogSeverity severity,
|
||||
std::string* result);
|
||||
|
||||
~LogMessage();
|
||||
|
||||
std::ostream& stream() { return stream_; }
|
||||
|
||||
private:
|
||||
LogSeverity severity_;
|
||||
std::ostringstream stream_;
|
||||
|
||||
// The file and line information passed in to the constructor.
|
||||
const char* file_;
|
||||
const int line_;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Stores the current value of GetLastError in the constructor and restores
|
||||
// it in the destructor by calling SetLastError.
|
||||
// This is useful since the LogMessage class uses a lot of Win32 calls
|
||||
// that will lose the value of GLE and the code that called the log function
|
||||
// will have lost the thread error value when the log call returns.
|
||||
class SaveLastError {
|
||||
public:
|
||||
SaveLastError();
|
||||
~SaveLastError();
|
||||
|
||||
unsigned long get_error() const { return last_error_; }
|
||||
|
||||
protected:
|
||||
unsigned long last_error_;
|
||||
};
|
||||
|
||||
SaveLastError last_error_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LogMessage);
|
||||
};
|
||||
|
||||
// A non-macro interface to the log facility; (useful
|
||||
// when the logging level is not a compile-time constant).
|
||||
inline void LogAtLevel(int const log_level, std::string const &msg) {
|
||||
LogMessage(__FILE__, __LINE__, log_level).stream() << msg;
|
||||
}
|
||||
|
||||
// This class is used to explicitly ignore values in the conditional
|
||||
// logging macros. This avoids compiler warnings like "value computed
|
||||
// is not used" and "statement has no effect".
|
||||
class LogMessageVoidify {
|
||||
public:
|
||||
LogMessageVoidify() { }
|
||||
// This has to be an operator with a precedence lower than << but
|
||||
// higher than ?:
|
||||
void operator&(std::ostream&) { }
|
||||
};
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef unsigned long SystemErrorCode;
|
||||
#elif defined(OS_POSIX)
|
||||
typedef int SystemErrorCode;
|
||||
#endif
|
||||
|
||||
// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
|
||||
// pull in windows.h just for GetLastError() and DWORD.
|
||||
SystemErrorCode GetLastSystemErrorCode();
|
||||
std::string SystemErrorCodeToString(SystemErrorCode error_code);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Appends a formatted system message of the GetLastError() type.
|
||||
class Win32ErrorLogMessage {
|
||||
public:
|
||||
Win32ErrorLogMessage(const char* file,
|
||||
int line,
|
||||
LogSeverity severity,
|
||||
SystemErrorCode err);
|
||||
|
||||
// Appends the error message before destructing the encapsulated class.
|
||||
~Win32ErrorLogMessage();
|
||||
|
||||
std::ostream& stream() { return log_message_.stream(); }
|
||||
|
||||
private:
|
||||
SystemErrorCode err_;
|
||||
LogMessage log_message_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
|
||||
};
|
||||
#elif defined(OS_POSIX)
|
||||
// Appends a formatted system message of the errno type
|
||||
class ErrnoLogMessage {
|
||||
public:
|
||||
ErrnoLogMessage(const char* file,
|
||||
int line,
|
||||
LogSeverity severity,
|
||||
SystemErrorCode err);
|
||||
|
||||
// Appends the error message before destructing the encapsulated class.
|
||||
~ErrnoLogMessage();
|
||||
|
||||
std::ostream& stream() { return log_message_.stream(); }
|
||||
|
||||
private:
|
||||
SystemErrorCode err_;
|
||||
LogMessage log_message_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
|
||||
};
|
||||
#endif // OS_WIN
|
||||
|
||||
} // namespace logging
|
||||
} // namespace cef
|
||||
|
||||
// These functions are provided as a convenience for logging, which is where we
|
||||
// use streams (it is against Google style to use streams in other places). It
|
||||
// is designed to allow you to emit non-ASCII Unicode strings to the log file,
|
||||
// which is normally ASCII. It is relatively slow, so try not to use it for
|
||||
// common cases. Non-ASCII characters will be converted to UTF-8 by these
|
||||
// operators.
|
||||
std::ostream& operator<<(std::ostream& out, const wchar_t* wstr);
|
||||
inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
|
||||
return out << wstr.c_str();
|
||||
}
|
||||
|
||||
// The NOTIMPLEMENTED() macro annotates codepaths which have
|
||||
// not been implemented yet.
|
||||
//
|
||||
// The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY:
|
||||
// 0 -- Do nothing (stripped by compiler)
|
||||
// 1 -- Warn at compile time
|
||||
// 2 -- Fail at compile time
|
||||
// 3 -- Fail at runtime (DCHECK)
|
||||
// 4 -- [default] LOG(ERROR) at runtime
|
||||
// 5 -- LOG(ERROR) at runtime, only once per call-site
|
||||
|
||||
#ifndef NOTIMPLEMENTED_POLICY
|
||||
#if defined(OS_ANDROID) && defined(OFFICIAL_BUILD)
|
||||
#define NOTIMPLEMENTED_POLICY 0
|
||||
#else
|
||||
// Select default policy: LOG(ERROR)
|
||||
#define NOTIMPLEMENTED_POLICY 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(COMPILER_GCC)
|
||||
// On Linux, with GCC, we can use __PRETTY_FUNCTION__ to get the demangled name
|
||||
// of the current function in the NOTIMPLEMENTED message.
|
||||
#define NOTIMPLEMENTED_MSG "Not implemented reached in " << __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED"
|
||||
#endif
|
||||
|
||||
#if NOTIMPLEMENTED_POLICY == 0
|
||||
#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS
|
||||
#elif NOTIMPLEMENTED_POLICY == 1
|
||||
// TODO, figure out how to generate a warning
|
||||
#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
|
||||
#elif NOTIMPLEMENTED_POLICY == 2
|
||||
#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
|
||||
#elif NOTIMPLEMENTED_POLICY == 3
|
||||
#define NOTIMPLEMENTED() NOTREACHED()
|
||||
#elif NOTIMPLEMENTED_POLICY == 4
|
||||
#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG
|
||||
#elif NOTIMPLEMENTED_POLICY == 5
|
||||
#define NOTIMPLEMENTED() do {\
|
||||
static bool logged_once = false;\
|
||||
LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\
|
||||
logged_once = true;\
|
||||
} while(0);\
|
||||
EAT_STREAM_PARAMETERS
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_LOGGING_H_
|
218
include/base/cef_macros.h
Normal file
218
include/base/cef_macros.h
Normal file
@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_MACROS_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_MACROS_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/macros.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <stddef.h> // For size_t.
|
||||
|
||||
#if !defined(ALLOW_THIS_IN_INITIALIZER_LIST)
|
||||
#if defined(COMPILER_MSVC)
|
||||
|
||||
// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
|
||||
// The warning remains disabled until popped by MSVC_POP_WARNING.
|
||||
#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
|
||||
__pragma(warning(disable:n))
|
||||
|
||||
// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level
|
||||
// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all
|
||||
// warnings.
|
||||
#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n))
|
||||
|
||||
// Pop effects of innermost MSVC_PUSH_* macro.
|
||||
#define MSVC_POP_WARNING() __pragma(warning(pop))
|
||||
|
||||
// Allows |this| to be passed as an argument in constructor initializer lists.
|
||||
// This uses push/pop instead of the seemingly simpler suppress feature to avoid
|
||||
// having the warning be disabled for more than just |code|.
|
||||
//
|
||||
// Example usage:
|
||||
// Foo::Foo() : x(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(y(this)), z(3) {}
|
||||
//
|
||||
// Compiler warning C4355: 'this': used in base member initializer list:
|
||||
// http://msdn.microsoft.com/en-us/library/3c594ae3(VS.80).aspx
|
||||
#define ALLOW_THIS_IN_INITIALIZER_LIST(code) MSVC_PUSH_DISABLE_WARNING(4355) \
|
||||
code \
|
||||
MSVC_POP_WARNING()
|
||||
#else // !COMPILER_MSVC
|
||||
|
||||
#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code
|
||||
|
||||
#endif // !COMPILER_MSVC
|
||||
#endif // !ALLOW_THIS_IN_INITIALIZER_LIST
|
||||
|
||||
#if !defined(arraysize)
|
||||
|
||||
// The arraysize(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example. If you use arraysize on
|
||||
// a pointer by mistake, you will get a compile-time error.
|
||||
//
|
||||
// One caveat is that arraysize() doesn't accept any array of an
|
||||
// anonymous type or a type defined inside a function. In these rare
|
||||
// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
|
||||
// due to a limitation in C++'s template system. The limitation might
|
||||
// eventually be removed, but it hasn't happened yet.
|
||||
|
||||
// This template function declaration is used in defining arraysize.
|
||||
// Note that the function doesn't need an implementation, as we only
|
||||
// use its type.
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(T (&array)[N]))[N];
|
||||
|
||||
// That gcc wants both of these prototypes seems mysterious. VC, for
|
||||
// its part, can't decide which to use (another mystery). Matching of
|
||||
// template overloads: the final frontier.
|
||||
#ifndef _MSC_VER
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||
#endif
|
||||
|
||||
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
||||
|
||||
#endif // !arraysize
|
||||
|
||||
#if !defined(DISALLOW_COPY_AND_ASSIGN)
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
#endif // !DISALLOW_COPY_AND_ASSIGN
|
||||
|
||||
#if !defined(DISALLOW_IMPLICIT_CONSTRUCTORS)
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
|
||||
#endif // !DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
|
||||
#if !defined(COMPILE_ASSERT)
|
||||
|
||||
// The COMPILE_ASSERT macro can be used to verify that a compile time
|
||||
// expression is true. For example, you could use it to verify the
|
||||
// size of a static array:
|
||||
//
|
||||
// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
|
||||
// content_type_names_incorrect_size);
|
||||
//
|
||||
// or to make sure a struct is smaller than a certain size:
|
||||
//
|
||||
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
|
||||
//
|
||||
// The second argument to the macro is the name of the variable. If
|
||||
// the expression is false, most compilers will issue a warning/error
|
||||
// containing the name of the variable.
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
// Under C++11, just use static_assert.
|
||||
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
|
||||
|
||||
#else
|
||||
|
||||
namespace cef {
|
||||
|
||||
template <bool>
|
||||
struct CompileAssert {
|
||||
};
|
||||
|
||||
} // namespace cef
|
||||
|
||||
#define COMPILE_ASSERT(expr, msg) \
|
||||
typedef cef::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] \
|
||||
ALLOW_UNUSED_TYPE
|
||||
|
||||
// Implementation details of COMPILE_ASSERT:
|
||||
//
|
||||
// - COMPILE_ASSERT works by defining an array type that has -1
|
||||
// elements (and thus is invalid) when the expression is false.
|
||||
//
|
||||
// - The simpler definition
|
||||
//
|
||||
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||
//
|
||||
// does not work, as gcc supports variable-length arrays whose sizes
|
||||
// are determined at run-time (this is gcc's extension and not part
|
||||
// of the C++ standard). As a result, gcc fails to reject the
|
||||
// following code with the simple definition:
|
||||
//
|
||||
// int foo;
|
||||
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
|
||||
// // not a compile-time constant.
|
||||
//
|
||||
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||
// expr is a compile-time constant. (Template arguments must be
|
||||
// determined at compile-time.)
|
||||
//
|
||||
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
|
||||
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||
//
|
||||
// CompileAssert<bool(expr)>
|
||||
//
|
||||
// instead, these compilers will refuse to compile
|
||||
//
|
||||
// COMPILE_ASSERT(5 > 0, some_message);
|
||||
//
|
||||
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||
// template argument list.)
|
||||
//
|
||||
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||
//
|
||||
// ((expr) ? 1 : -1).
|
||||
//
|
||||
// This is to avoid running into a bug in MS VC 7.1, which
|
||||
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||
|
||||
#endif // !(__cplusplus >= 201103L)
|
||||
|
||||
#endif // !defined(COMPILE_ASSERT)
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_MACROS_H_
|
259
include/base/cef_move.h
Normal file
259
include/base/cef_move.h
Normal file
@ -0,0 +1,259 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_MOVE_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_MOVE_H_
|
||||
|
||||
#if defined(MOVE_ONLY_TYPE_FOR_CPP_03)
|
||||
// Do nothing if the macro in this header has already been defined.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/move.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
// Macro with the boilerplate that makes a type move-only in C++03.
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
|
||||
// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
|
||||
// the first line in a class declaration.
|
||||
//
|
||||
// A class using this macro must call .Pass() (or somehow be an r-value already)
|
||||
// before it can be:
|
||||
//
|
||||
// * Passed as a function argument
|
||||
// * Used as the right-hand side of an assignment
|
||||
// * Returned from a function
|
||||
//
|
||||
// Each class will still need to define their own "move constructor" and "move
|
||||
// operator=" to make this useful. Here's an example of the macro, the move
|
||||
// constructor, and the move operator= from the scoped_ptr class:
|
||||
//
|
||||
// template <typename T>
|
||||
// class scoped_ptr {
|
||||
// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||
// public:
|
||||
// scoped_ptr(RValue& other) : ptr_(other.release()) { }
|
||||
// scoped_ptr& operator=(RValue& other) {
|
||||
// swap(other);
|
||||
// return *this;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Note that the constructor must NOT be marked explicit.
|
||||
//
|
||||
// For consistency, the second parameter to the macro should always be RValue
|
||||
// unless you have a strong reason to do otherwise. It is only exposed as a
|
||||
// macro parameter so that the move constructor and move operator= don't look
|
||||
// like they're using a phantom type.
|
||||
//
|
||||
//
|
||||
// HOW THIS WORKS
|
||||
//
|
||||
// For a thorough explanation of this technique, see:
|
||||
//
|
||||
// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
|
||||
//
|
||||
// The summary is that we take advantage of 2 properties:
|
||||
//
|
||||
// 1) non-const references will not bind to r-values.
|
||||
// 2) C++ can apply one user-defined conversion when initializing a
|
||||
// variable.
|
||||
//
|
||||
// The first lets us disable the copy constructor and assignment operator
|
||||
// by declaring private version of them with a non-const reference parameter.
|
||||
//
|
||||
// For l-values, direct initialization still fails like in
|
||||
// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
|
||||
// operators are private.
|
||||
//
|
||||
// For r-values, the situation is different. The copy constructor and
|
||||
// assignment operator are not viable due to (1), so we are trying to call
|
||||
// a non-existent constructor and non-existing operator= rather than a private
|
||||
// one. Since we have not committed an error quite yet, we can provide an
|
||||
// alternate conversion sequence and a constructor. We add
|
||||
//
|
||||
// * a private struct named "RValue"
|
||||
// * a user-defined conversion "operator RValue()"
|
||||
// * a "move constructor" and "move operator=" that take the RValue& as
|
||||
// their sole parameter.
|
||||
//
|
||||
// Only r-values will trigger this sequence and execute our "move constructor"
|
||||
// or "move operator=." L-values will match the private copy constructor and
|
||||
// operator= first giving a "private in this context" error. This combination
|
||||
// gives us a move-only type.
|
||||
//
|
||||
// For signaling a destructive transfer of data from an l-value, we provide a
|
||||
// method named Pass() which creates an r-value for the current instance
|
||||
// triggering the move constructor or move operator=.
|
||||
//
|
||||
// Other ways to get r-values is to use the result of an expression like a
|
||||
// function call.
|
||||
//
|
||||
// Here's an example with comments explaining what gets triggered where:
|
||||
//
|
||||
// class Foo {
|
||||
// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
|
||||
//
|
||||
// public:
|
||||
// ... API ...
|
||||
// Foo(RValue other); // Move constructor.
|
||||
// Foo& operator=(RValue rhs); // Move operator=
|
||||
// };
|
||||
//
|
||||
// Foo MakeFoo(); // Function that returns a Foo.
|
||||
//
|
||||
// Foo f;
|
||||
// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context.
|
||||
// Foo f_assign;
|
||||
// f_assign = f; // ERROR: operator=(Foo&) is private in this context.
|
||||
//
|
||||
//
|
||||
// Foo f(MakeFoo()); // R-value so alternate conversion executed.
|
||||
// Foo f_copy(f.Pass()); // R-value so alternate conversion executed.
|
||||
// f = f_copy.Pass(); // R-value so alternate conversion executed.
|
||||
//
|
||||
//
|
||||
// IMPLEMENTATION SUBTLETIES WITH RValue
|
||||
//
|
||||
// The RValue struct is just a container for a pointer back to the original
|
||||
// object. It should only ever be created as a temporary, and no external
|
||||
// class should ever declare it or use it in a parameter.
|
||||
//
|
||||
// It is tempting to want to use the RValue type in function parameters, but
|
||||
// excluding the limited usage here for the move constructor and move
|
||||
// operator=, doing so would mean that the function could take both r-values
|
||||
// and l-values equially which is unexpected. See COMPARED To Boost.Move for
|
||||
// more details.
|
||||
//
|
||||
// An alternate, and incorrect, implementation of the RValue class used by
|
||||
// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
|
||||
// is then used in place of RValue in the various operators. The RValue& is
|
||||
// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal
|
||||
// of never creating a temporary RValue struct even with optimizations
|
||||
// disabled. Also, by virtue of inheritance you can treat the RValue
|
||||
// reference as if it were the move-only type itself. Unfortunately,
|
||||
// using the result of this reinterpret_cast<> is actually undefined behavior
|
||||
// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
|
||||
// will generate non-working code.
|
||||
//
|
||||
// In optimized builds, both implementations generate the same assembly so we
|
||||
// choose the one that adheres to the standard.
|
||||
//
|
||||
//
|
||||
// WHY HAVE typedef void MoveOnlyTypeForCPP03
|
||||
//
|
||||
// Callback<>/Bind() needs to understand movable-but-not-copyable semantics
|
||||
// to call .Pass() appropriately when it is expected to transfer the value.
|
||||
// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check
|
||||
// easy and automatic in helper templates for Callback<>/Bind().
|
||||
// See IsMoveOnlyType template and its usage in base/callback_internal.h
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// COMPARED TO C++11
|
||||
//
|
||||
// In C++11, you would implement this functionality using an r-value reference
|
||||
// and our .Pass() method would be replaced with a call to std::move().
|
||||
//
|
||||
// This emulation also has a deficiency where it uses up the single
|
||||
// user-defined conversion allowed by C++ during initialization. This can
|
||||
// cause problems in some API edge cases. For instance, in scoped_ptr, it is
|
||||
// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
|
||||
// value of type scoped_ptr<Child> even if you add a constructor to
|
||||
// scoped_ptr<> that would make it look like it should work. C++11 does not
|
||||
// have this deficiency.
|
||||
//
|
||||
//
|
||||
// COMPARED TO Boost.Move
|
||||
//
|
||||
// Our implementation similar to Boost.Move, but we keep the RValue struct
|
||||
// private to the move-only type, and we don't use the reinterpret_cast<> hack.
|
||||
//
|
||||
// In Boost.Move, RValue is the boost::rv<> template. This type can be used
|
||||
// when writing APIs like:
|
||||
//
|
||||
// void MyFunc(boost::rv<Foo>& f)
|
||||
//
|
||||
// that can take advantage of rv<> to avoid extra copies of a type. However you
|
||||
// would still be able to call this version of MyFunc with an l-value:
|
||||
//
|
||||
// Foo f;
|
||||
// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass().
|
||||
//
|
||||
// unless someone is very careful to also declare a parallel override like:
|
||||
//
|
||||
// void MyFunc(const Foo& f)
|
||||
//
|
||||
// that would catch the l-values first. This was declared unsafe in C++11 and
|
||||
// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot
|
||||
// ensure this in C++03.
|
||||
//
|
||||
// Since we have no need for writing such APIs yet, our implementation keeps
|
||||
// RValue private and uses a .Pass() method to do the conversion instead of
|
||||
// trying to write a version of "std::move()." Writing an API like std::move()
|
||||
// would require the RValue struct to be public.
|
||||
//
|
||||
//
|
||||
// CAVEATS
|
||||
//
|
||||
// If you include a move-only type as a field inside a class that does not
|
||||
// explicitly declare a copy constructor, the containing class's implicit
|
||||
// copy constructor will change from Containing(const Containing&) to
|
||||
// Containing(Containing&). This can cause some unexpected errors.
|
||||
//
|
||||
// http://llvm.org/bugs/show_bug.cgi?id=11528
|
||||
//
|
||||
// The workaround is to explicitly declare your copy constructor.
|
||||
//
|
||||
#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
|
||||
private: \
|
||||
struct rvalue_type { \
|
||||
explicit rvalue_type(type* object) : object(object) {} \
|
||||
type* object; \
|
||||
}; \
|
||||
type(type&); \
|
||||
void operator=(type&); \
|
||||
public: \
|
||||
operator rvalue_type() { return rvalue_type(this); } \
|
||||
type Pass() { return type(rvalue_type(this)); } \
|
||||
typedef void MoveOnlyTypeForCPP03; \
|
||||
private:
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_MOVE_H_
|
113
include/base/cef_platform_thread.h
Normal file
113
include/base/cef_platform_thread.h
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// WARNING: You should *NOT* be using this class directly. PlatformThread is
|
||||
// the low-level platform-specific abstraction to the OS's threading interface.
|
||||
// You should instead be using a message-loop driven Thread, see thread.h.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
|
||||
#define CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
|
||||
|
||||
#if defined(BASE_THREADING_PLATFORM_THREAD_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/threading/platform_thread.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/internal/cef_thread_internal.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Used for logging. Always an integer value.
|
||||
typedef cef_platform_thread_id_t PlatformThreadId;
|
||||
|
||||
// Used for thread checking and debugging.
|
||||
// Meant to be as fast as possible.
|
||||
// These are produced by PlatformThread::CurrentRef(), and used to later
|
||||
// check if we are on the same thread or not by using ==. These are safe
|
||||
// to copy between threads, but can't be copied to another process as they
|
||||
// have no meaning there. Also, the internal identifier can be re-used
|
||||
// after a thread dies, so a PlatformThreadRef cannot be reliably used
|
||||
// to distinguish a new thread from an old, dead thread.
|
||||
class PlatformThreadRef {
|
||||
public:
|
||||
typedef cef_platform_thread_handle_t RefType;
|
||||
|
||||
PlatformThreadRef()
|
||||
: id_(0) {
|
||||
}
|
||||
|
||||
explicit PlatformThreadRef(RefType id)
|
||||
: id_(id) {
|
||||
}
|
||||
|
||||
bool operator==(PlatformThreadRef other) const {
|
||||
return id_ == other.id_;
|
||||
}
|
||||
|
||||
bool is_null() const {
|
||||
return id_ == 0;
|
||||
}
|
||||
private:
|
||||
RefType id_;
|
||||
};
|
||||
|
||||
// A namespace for low-level thread functions.
|
||||
// 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 {
|
||||
|
||||
// Gets the current thread id, which may be useful for logging purposes.
|
||||
inline PlatformThreadId CurrentId() {
|
||||
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.
|
||||
inline PlatformThreadRef CurrentRef() {
|
||||
return PlatformThreadRef(cef_get_current_platform_thread_handle());
|
||||
}
|
||||
|
||||
} // namespace PlatformThread
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
|
386
include/base/cef_ref_counted.h
Normal file
386
include/base/cef_ref_counted.h
Normal file
@ -0,0 +1,386 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_MEMORY_REF_COUNTED_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/memory/ref_counted.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "include/base/cef_atomic_ref_count.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#ifndef NDEBUG
|
||||
#include "include/base/cef_logging.h"
|
||||
#endif
|
||||
#include "include/base/cef_thread_collision_warner.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace subtle {
|
||||
|
||||
class RefCountedBase {
|
||||
public:
|
||||
bool HasOneRef() const { return ref_count_ == 1; }
|
||||
|
||||
protected:
|
||||
RefCountedBase()
|
||||
: ref_count_(0)
|
||||
#ifndef NDEBUG
|
||||
, in_dtor_(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
~RefCountedBase() {
|
||||
#ifndef NDEBUG
|
||||
DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void AddRef() const {
|
||||
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
|
||||
// Current thread books the critical section "AddRelease"
|
||||
// without release it.
|
||||
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
|
||||
#ifndef NDEBUG
|
||||
DCHECK(!in_dtor_);
|
||||
#endif
|
||||
++ref_count_;
|
||||
}
|
||||
|
||||
// Returns true if the object should self-delete.
|
||||
bool Release() const {
|
||||
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
|
||||
// Current thread books the critical section "AddRelease"
|
||||
// without release it.
|
||||
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
|
||||
#ifndef NDEBUG
|
||||
DCHECK(!in_dtor_);
|
||||
#endif
|
||||
if (--ref_count_ == 0) {
|
||||
#ifndef NDEBUG
|
||||
in_dtor_ = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable int ref_count_;
|
||||
#ifndef NDEBUG
|
||||
mutable bool in_dtor_;
|
||||
#endif
|
||||
|
||||
DFAKE_MUTEX(add_release_);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
|
||||
};
|
||||
|
||||
class RefCountedThreadSafeBase {
|
||||
public:
|
||||
bool HasOneRef() const;
|
||||
|
||||
protected:
|
||||
RefCountedThreadSafeBase();
|
||||
~RefCountedThreadSafeBase();
|
||||
|
||||
void AddRef() const;
|
||||
|
||||
// Returns true if the object should self-delete.
|
||||
bool Release() const;
|
||||
|
||||
private:
|
||||
mutable AtomicRefCount ref_count_;
|
||||
#ifndef NDEBUG
|
||||
mutable bool in_dtor_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
|
||||
};
|
||||
|
||||
} // namespace subtle
|
||||
|
||||
//
|
||||
// A base class for reference counted classes. Otherwise, known as a cheap
|
||||
// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your
|
||||
// class from it like so:
|
||||
//
|
||||
// class MyFoo : public base::RefCounted<MyFoo> {
|
||||
// ...
|
||||
// private:
|
||||
// friend class base::RefCounted<MyFoo>;
|
||||
// ~MyFoo();
|
||||
// };
|
||||
//
|
||||
// You should always make your destructor private, to avoid any code deleting
|
||||
// the object accidently while there are references to it.
|
||||
template <class T>
|
||||
class RefCounted : public subtle::RefCountedBase {
|
||||
public:
|
||||
RefCounted() {}
|
||||
|
||||
void AddRef() const {
|
||||
subtle::RefCountedBase::AddRef();
|
||||
}
|
||||
|
||||
void Release() const {
|
||||
if (subtle::RefCountedBase::Release()) {
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
~RefCounted() {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
|
||||
};
|
||||
|
||||
// Forward declaration.
|
||||
template <class T, typename Traits> 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.
|
||||
template<typename T>
|
||||
struct DefaultRefCountedThreadSafeTraits {
|
||||
static void Destruct(const T* x) {
|
||||
// Delete through RefCountedThreadSafe to make child classes only need to be
|
||||
// friend with RefCountedThreadSafe instead of this struct, which is an
|
||||
// implementation detail.
|
||||
RefCountedThreadSafe<T,
|
||||
DefaultRefCountedThreadSafeTraits>::DeleteInternal(x);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// A thread-safe variant of RefCounted<T>
|
||||
//
|
||||
// class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// If you're using the default trait, then you should add compile time
|
||||
// asserts that no one else is deleting your object. i.e.
|
||||
// private:
|
||||
// friend class base::RefCountedThreadSafe<MyFoo>;
|
||||
// ~MyFoo();
|
||||
template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
|
||||
class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
|
||||
public:
|
||||
RefCountedThreadSafe() {}
|
||||
|
||||
void AddRef() const {
|
||||
subtle::RefCountedThreadSafeBase::AddRef();
|
||||
}
|
||||
|
||||
void Release() const {
|
||||
if (subtle::RefCountedThreadSafeBase::Release()) {
|
||||
Traits::Destruct(static_cast<const T*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
~RefCountedThreadSafe() {}
|
||||
|
||||
private:
|
||||
friend struct DefaultRefCountedThreadSafeTraits<T>;
|
||||
static void DeleteInternal(const T* x) { delete x; }
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
|
||||
};
|
||||
|
||||
//
|
||||
// A thread-safe wrapper for some piece of data so we can place other
|
||||
// things in scoped_refptrs<>.
|
||||
//
|
||||
template<typename T>
|
||||
class RefCountedData
|
||||
: public base::RefCountedThreadSafe< base::RefCountedData<T> > {
|
||||
public:
|
||||
RefCountedData() : data() {}
|
||||
RefCountedData(const T& in_value) : data(in_value) {}
|
||||
|
||||
T data;
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<base::RefCountedData<T> >;
|
||||
~RefCountedData() {}
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
//
|
||||
// A smart pointer class for reference counted objects. Use this class instead
|
||||
// of calling AddRef and Release manually on a reference counted object to
|
||||
// avoid common memory leaks caused by forgetting to Release an object
|
||||
// reference. Sample usage:
|
||||
//
|
||||
// class MyFoo : public RefCounted<MyFoo> {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// void some_function() {
|
||||
// scoped_refptr<MyFoo> foo = new MyFoo();
|
||||
// foo->Method(param);
|
||||
// // |foo| is released when this function returns
|
||||
// }
|
||||
//
|
||||
// void some_other_function() {
|
||||
// scoped_refptr<MyFoo> foo = new MyFoo();
|
||||
// ...
|
||||
// foo = NULL; // explicitly releases |foo|
|
||||
// ...
|
||||
// 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
|
||||
// references between the two objects, like so:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = new MyFoo();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b.swap(a);
|
||||
// // now, |b| references the MyFoo object, and |a| references NULL.
|
||||
// }
|
||||
//
|
||||
// To make both |a| and |b| in the above example reference the same MyFoo
|
||||
// object, simply use the assignment operator:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = new MyFoo();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b = a;
|
||||
// // now, |a| and |b| each own a reference to the same MyFoo object.
|
||||
// }
|
||||
//
|
||||
template <class T>
|
||||
class scoped_refptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
scoped_refptr() : ptr_(NULL) {
|
||||
}
|
||||
|
||||
scoped_refptr(T* p) : ptr_(p) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
~scoped_refptr() {
|
||||
if (ptr_)
|
||||
ptr_->Release();
|
||||
}
|
||||
|
||||
T* get() const { return ptr_; }
|
||||
|
||||
// Allow scoped_refptr<C> to be used in boolean expression
|
||||
// and comparison operations.
|
||||
operator T*() const { return ptr_; }
|
||||
|
||||
T* operator->() const {
|
||||
assert(ptr_ != NULL);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(T* p) {
|
||||
// AddRef first so that self assignment should work
|
||||
if (p)
|
||||
p->AddRef();
|
||||
T* old_ptr = ptr_;
|
||||
ptr_ = p;
|
||||
if (old_ptr)
|
||||
old_ptr->Release();
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
|
||||
return *this = r.ptr_;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
|
||||
return *this = r.get();
|
||||
}
|
||||
|
||||
void swap(T** pp) {
|
||||
T* p = ptr_;
|
||||
ptr_ = *pp;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void swap(scoped_refptr<T>& r) {
|
||||
swap(&r.ptr_);
|
||||
}
|
||||
|
||||
protected:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
|
||||
// having to retype all the template arguments
|
||||
template <typename T>
|
||||
scoped_refptr<T> make_scoped_refptr(T* t) {
|
||||
return scoped_refptr<T>(t);
|
||||
}
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
|
624
include/base/cef_scoped_ptr.h
Normal file
624
include/base/cef_scoped_ptr.h
Normal file
@ -0,0 +1,624 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Scopers help you manage ownership of a pointer, helping you easily manage a
|
||||
// pointer within a scope, and automatically destroying the pointer at the end
|
||||
// of a scope. There are two main classes you will use, which correspond to the
|
||||
// operators new/delete and new[]/delete[].
|
||||
//
|
||||
// Example usage (scoped_ptr<T>):
|
||||
// {
|
||||
// scoped_ptr<Foo> foo(new Foo("wee"));
|
||||
// } // foo goes out of scope, releasing the pointer with it.
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> foo; // No pointer managed.
|
||||
// foo.reset(new Foo("wee")); // Now a pointer is managed.
|
||||
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
|
||||
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
|
||||
// foo->Method(); // Foo::Method() called.
|
||||
// foo.get()->Method(); // Foo::Method() called.
|
||||
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
|
||||
// // manages a pointer.
|
||||
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
|
||||
// foo.reset(); // Foo("wee4") destroyed, foo no longer
|
||||
// // manages a pointer.
|
||||
// } // foo wasn't managing a pointer, so nothing was destroyed.
|
||||
//
|
||||
// Example usage (scoped_ptr<T[]>):
|
||||
// {
|
||||
// scoped_ptr<Foo[]> foo(new Foo[100]);
|
||||
// foo.get()->Method(); // Foo::Method on the 0th element.
|
||||
// foo[10].Method(); // Foo::Method on the 10th element.
|
||||
// }
|
||||
//
|
||||
// These scopers also implement part of the functionality of C++11 unique_ptr
|
||||
// in that they are "movable but not copyable." You can use the scopers in
|
||||
// the parameter and return types of functions to signify ownership transfer
|
||||
// in to and out of a function. When calling a function that has a scoper
|
||||
// as the argument type, it must be called with the result of an analogous
|
||||
// scoper's Pass() function or another function that generates a temporary;
|
||||
// passing by copy will NOT work. Here is an example using scoped_ptr:
|
||||
//
|
||||
// void TakesOwnership(scoped_ptr<Foo> arg) {
|
||||
// // Do something with arg
|
||||
// }
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// // No need for calling Pass() because we are constructing a temporary
|
||||
// // for the return value.
|
||||
// return scoped_ptr<Foo>(new Foo("new"));
|
||||
// }
|
||||
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
|
||||
// return arg.Pass();
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
|
||||
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
|
||||
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
|
||||
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
|
||||
// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
|
||||
// }
|
||||
//
|
||||
// Notice that if you do not call Pass() when returning from PassThru(), or
|
||||
// when invoking TakesOwnership(), the code will not compile because scopers
|
||||
// are not copyable; they only implement move semantics which require calling
|
||||
// the Pass() function to signify a destructive transfer of state. CreateFoo()
|
||||
// is different though because we are constructing a temporary on the return
|
||||
// line and thus can avoid needing to call Pass().
|
||||
//
|
||||
// Pass() properly handles upcast in initialization, i.e. you can use a
|
||||
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
|
||||
//
|
||||
// scoped_ptr<Foo> foo(new Foo());
|
||||
// scoped_ptr<FooParent> parent(foo.Pass());
|
||||
//
|
||||
// PassAs<>() should be used to upcast return value in return statement:
|
||||
//
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// scoped_ptr<FooChild> result(new FooChild());
|
||||
// return result.PassAs<Foo>();
|
||||
// }
|
||||
//
|
||||
// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
|
||||
// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_MEMORY_SCOPED_PTR_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
// This is an implementation designed to match the anticipated future TR2
|
||||
// implementation of the scoped_ptr class.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm> // For std::swap().
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_move.h"
|
||||
#include "include/base/cef_template_util.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace subtle {
|
||||
class RefCountedBase;
|
||||
class RefCountedThreadSafeBase;
|
||||
} // namespace subtle
|
||||
|
||||
// Function object which deletes its parameter, which must be a pointer.
|
||||
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
|
||||
// invokes 'delete'. The default deleter for scoped_ptr<T>.
|
||||
template <class T>
|
||||
struct DefaultDeleter {
|
||||
DefaultDeleter() {}
|
||||
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
|
||||
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
|
||||
// if U* is implicitly convertible to T* and U is not an array type.
|
||||
//
|
||||
// Correct implementation should use SFINAE to disable this
|
||||
// constructor. However, since there are no other 1-argument constructors,
|
||||
// using a COMPILE_ASSERT() based on is_convertible<> and requiring
|
||||
// complete types is simpler and will cause compile failures for equivalent
|
||||
// misuses.
|
||||
//
|
||||
// Note, the is_convertible<U*, T*> check also ensures that U is not an
|
||||
// array. T is guaranteed to be a non-array, so any U* where U is an array
|
||||
// cannot convert to T*.
|
||||
enum { T_must_be_complete = sizeof(T) };
|
||||
enum { U_must_be_complete = sizeof(U) };
|
||||
COMPILE_ASSERT((base::is_convertible<U*, T*>::value),
|
||||
U_ptr_must_implicitly_convert_to_T_ptr);
|
||||
}
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of DefaultDeleter for array types.
|
||||
template <class T>
|
||||
struct DefaultDeleter<T[]> {
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable this operator for any U != T because it is undefined to execute
|
||||
// an array delete when the static type of the array mismatches the dynamic
|
||||
// type.
|
||||
//
|
||||
// References:
|
||||
// C++98 [expr.delete]p3
|
||||
// http://cplusplus.github.com/LWG/lwg-defects.html#938
|
||||
template <typename U> void operator()(U* array) const;
|
||||
};
|
||||
|
||||
template <class T, int n>
|
||||
struct DefaultDeleter<T[n]> {
|
||||
// Never allow someone to declare something like scoped_ptr<int[10]>.
|
||||
COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
|
||||
};
|
||||
|
||||
// Function object which invokes 'free' on its parameter, which must be
|
||||
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
|
||||
//
|
||||
// scoped_ptr<int, base::FreeDeleter> foo_ptr(
|
||||
// static_cast<int*>(malloc(sizeof(int))));
|
||||
struct FreeDeleter {
|
||||
inline void operator()(void* ptr) const {
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
namespace cef_internal {
|
||||
|
||||
template <typename T> struct IsNotRefCounted {
|
||||
enum {
|
||||
value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
|
||||
!base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
|
||||
value
|
||||
};
|
||||
};
|
||||
|
||||
// Minimal implementation of the core logic of scoped_ptr, suitable for
|
||||
// reuse in both scoped_ptr and its specializations.
|
||||
template <class T, class D>
|
||||
class scoped_ptr_impl {
|
||||
public:
|
||||
explicit scoped_ptr_impl(T* p) : data_(p) { }
|
||||
|
||||
// Initializer for deleters that have data parameters.
|
||||
scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
|
||||
|
||||
// Templated constructor that destructively takes the value from another
|
||||
// scoped_ptr_impl.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
|
||||
: data_(other->release(), other->get_deleter()) {
|
||||
// We do not support move-only deleters. We could modify our move
|
||||
// emulation to have base::subtle::move() and base::subtle::forward()
|
||||
// functions that are imperfect emulations of their C++11 equivalents,
|
||||
// but until there's a requirement, just assume deleters are copyable.
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
void TakeState(scoped_ptr_impl<U, V>* other) {
|
||||
// See comment in templated constructor above regarding lack of support
|
||||
// for move-only deleters.
|
||||
reset(other->release());
|
||||
get_deleter() = other->get_deleter();
|
||||
}
|
||||
|
||||
~scoped_ptr_impl() {
|
||||
if (data_.ptr != NULL) {
|
||||
// Not using get_deleter() saves one function call in non-optimized
|
||||
// builds.
|
||||
static_cast<D&>(data_)(data_.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(T* p) {
|
||||
// This is a self-reset, which is no longer allowed: http://crbug.com/162971
|
||||
if (p != NULL && p == data_.ptr)
|
||||
abort();
|
||||
|
||||
// Note that running data_.ptr = p can lead to undefined behavior if
|
||||
// get_deleter()(get()) deletes this. In order to prevent this, reset()
|
||||
// should update the stored pointer before deleting its old value.
|
||||
//
|
||||
// However, changing reset() to use that behavior may cause current code to
|
||||
// break in unexpected ways. If the destruction of the owned object
|
||||
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
|
||||
// then it will incorrectly dispatch calls to |p| rather than the original
|
||||
// value of |data_.ptr|.
|
||||
//
|
||||
// During the transition period, set the stored pointer to NULL while
|
||||
// deleting the object. Eventually, this safety check will be removed to
|
||||
// prevent the scenario initially described from occuring and
|
||||
// http://crbug.com/176091 can be closed.
|
||||
T* old = data_.ptr;
|
||||
data_.ptr = NULL;
|
||||
if (old != NULL)
|
||||
static_cast<D&>(data_)(old);
|
||||
data_.ptr = p;
|
||||
}
|
||||
|
||||
T* get() const { return data_.ptr; }
|
||||
|
||||
D& get_deleter() { return data_; }
|
||||
const D& get_deleter() const { return data_; }
|
||||
|
||||
void swap(scoped_ptr_impl& p2) {
|
||||
// Standard swap idiom: 'using std::swap' ensures that std::swap is
|
||||
// present in the overload set, but we call swap unqualified so that
|
||||
// any more-specific overloads can be used, if available.
|
||||
using std::swap;
|
||||
swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
|
||||
swap(data_.ptr, p2.data_.ptr);
|
||||
}
|
||||
|
||||
T* release() {
|
||||
T* old_ptr = data_.ptr;
|
||||
data_.ptr = NULL;
|
||||
return old_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to allow type-converting constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr_impl;
|
||||
|
||||
// Use the empty base class optimization to allow us to have a D
|
||||
// member, while avoiding any space overhead for it when D is an
|
||||
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
|
||||
// discussion of this technique.
|
||||
struct Data : public D {
|
||||
explicit Data(T* ptr_in) : ptr(ptr_in) {}
|
||||
Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
Data data_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
} // namespace base
|
||||
|
||||
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||
// automatically deletes the pointer it holds (if any).
|
||||
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
|
||||
// Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||
// dereference it, you get the thread safety guarantees of T.
|
||||
//
|
||||
// The size of scoped_ptr is small. On most compilers, when using the
|
||||
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
|
||||
// increase the size proportional to whatever state they need to have. See
|
||||
// comments inside scoped_ptr_impl<> for details.
|
||||
//
|
||||
// Current implementation targets having a strict subset of C++11's
|
||||
// unique_ptr<> features. Known deficiencies include not supporting move-only
|
||||
// deleteres, function pointers as deleters, and deleters with reference
|
||||
// types.
|
||||
template <class T, class D = base::DefaultDeleter<T> >
|
||||
class scoped_ptr {
|
||||
MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||
|
||||
COMPILE_ASSERT(base::cef_internal::IsNotRefCounted<T>::value,
|
||||
T_is_refcounted_type_and_needs_scoped_refptr);
|
||||
|
||||
public:
|
||||
// The element and deleter types.
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// Constructor. Defaults to initializing with NULL.
|
||||
scoped_ptr() : impl_(NULL) { }
|
||||
|
||||
// Constructor. Takes ownership of p.
|
||||
explicit scoped_ptr(element_type* p) : impl_(p) { }
|
||||
|
||||
// Constructor. Allows initialization of a stateful deleter.
|
||||
scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
|
||||
|
||||
// Constructor. Allows construction from a scoped_ptr rvalue for a
|
||||
// convertible type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
|
||||
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
|
||||
// has different post-conditions if D is a reference type. Since this
|
||||
// implementation does not support deleters with reference type,
|
||||
// we do not need a separate move constructor allowing us to avoid one
|
||||
// use of SFINAE. You only need to care about this if you modify the
|
||||
// implementation of scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
|
||||
COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
|
||||
}
|
||||
|
||||
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||
|
||||
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
|
||||
// type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
|
||||
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
|
||||
// form has different requirements on for move-only Deleters. Since this
|
||||
// implementation does not support move-only Deleters, we do not need a
|
||||
// separate move assignment operator allowing us to avoid one use of SFINAE.
|
||||
// You only need to care about this if you modify the implementation of
|
||||
// scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
|
||||
COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
|
||||
impl_.TakeState(&rhs.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset. Deletes the currently owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* p = NULL) { impl_.reset(p); }
|
||||
|
||||
// Accessors to get the owned object.
|
||||
// operator* and operator-> will assert() if there is no current object.
|
||||
element_type& operator*() const {
|
||||
assert(impl_.get() != NULL);
|
||||
return *impl_.get();
|
||||
}
|
||||
element_type* operator->() const {
|
||||
assert(impl_.get() != NULL);
|
||||
return impl_.get();
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
//
|
||||
// Note that this trick is only safe when the == and != operators
|
||||
// are declared explicitly, as otherwise "scoped_ptr1 ==
|
||||
// scoped_ptr2" will compile but do the wrong thing (i.e., convert
|
||||
// to Testable and then do the comparison).
|
||||
private:
|
||||
typedef base::cef_internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(const element_type* p) const { return impl_.get() == p; }
|
||||
bool operator!=(const element_type* p) const { return impl_.get() != p; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
// C++98 doesn't support functions templates with default parameters which
|
||||
// makes it hard to write a PassAs() that understands converting the deleter
|
||||
// while preserving simple calling semantics.
|
||||
//
|
||||
// Until there is a use case for PassAs() with custom deleters, just ignore
|
||||
// the custom deleter.
|
||||
template <typename PassAsType>
|
||||
scoped_ptr<PassAsType> PassAs() {
|
||||
return scoped_ptr<PassAsType>(Pass());
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to reach into |impl_| in the constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr;
|
||||
base::cef_internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Forbidden for API compatibility with std::unique_ptr.
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
class scoped_ptr<T[], D> {
|
||||
MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||
|
||||
public:
|
||||
// The element and deleter types.
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// Constructor. Defaults to initializing with NULL.
|
||||
scoped_ptr() : impl_(NULL) { }
|
||||
|
||||
// Constructor. Stores the given array. Note that the argument's type
|
||||
// must exactly match T*. In particular:
|
||||
// - it cannot be a pointer to a type derived from T, because it is
|
||||
// inherently unsafe in the general case to access an array through a
|
||||
// pointer whose dynamic type does not match its static type (eg., if
|
||||
// T and the derived types had different sizes access would be
|
||||
// incorrectly calculated). Deletion is also always undefined
|
||||
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
|
||||
// - it cannot be NULL, because NULL is an integral expression, not a
|
||||
// pointer to T. Use the no-argument version instead of explicitly
|
||||
// passing NULL.
|
||||
// - it cannot be const-qualified differently from T per unique_ptr spec
|
||||
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
|
||||
// to work around this may use implicit_cast<const T*>().
|
||||
// However, because of the first bullet in this comment, users MUST
|
||||
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
|
||||
explicit scoped_ptr(element_type* array) : impl_(array) { }
|
||||
|
||||
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||
|
||||
// operator=. Move operator= for C++03 move emulation of this type.
|
||||
scoped_ptr& operator=(RValue rhs) {
|
||||
impl_.TakeState(&rhs.object->impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset. Deletes the currently owned array, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* array = NULL) { impl_.reset(array); }
|
||||
|
||||
// Accessors to get the owned array.
|
||||
element_type& operator[](size_t i) const {
|
||||
assert(impl_.get() != NULL);
|
||||
return impl_.get()[i];
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
private:
|
||||
typedef base::cef_internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(element_type* array) const { return impl_.get() == array; }
|
||||
bool operator!=(element_type* array) const { return impl_.get() != array; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
private:
|
||||
// Force element_type to be a complete type.
|
||||
enum { type_must_be_complete = sizeof(element_type) };
|
||||
|
||||
// Actually hold the data.
|
||||
base::cef_internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Disable initialization from any type other than element_type*, by
|
||||
// providing a constructor that matches such an initialization, but is
|
||||
// private and has no definition. This is disabled because it is not safe to
|
||||
// call delete[] on an array whose static type does not match its dynamic
|
||||
// type.
|
||||
template <typename U> explicit scoped_ptr(U* array);
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Disable reset() from any type other than element_type*, for the same
|
||||
// reasons as the constructor above.
|
||||
template <typename U> void reset(U* array);
|
||||
void reset(int disallow_reset_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
// Free functions
|
||||
template <class T, class D>
|
||||
void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator==(T* p1, const scoped_ptr<T, D>& p2) {
|
||||
return p1 == p2.get();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator!=(T* p1, const scoped_ptr<T, D>& p2) {
|
||||
return p1 != p2.get();
|
||||
}
|
||||
|
||||
// A function to convert T* into scoped_ptr<T>
|
||||
// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
||||
// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
||||
template <typename T>
|
||||
scoped_ptr<T> make_scoped_ptr(T* ptr) {
|
||||
return scoped_ptr<T>(ptr);
|
||||
}
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
|
227
include/base/cef_string16.h
Normal file
227
include/base/cef_string16.h
Normal file
@ -0,0 +1,227 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_STRING16_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_STRING16_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_STRINGS_STRING16_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/strings/string16.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
// WHAT:
|
||||
// A version of std::basic_string that provides 2-byte characters even when
|
||||
// wchar_t is not implemented as a 2-byte type. You can access this class as
|
||||
// string16. We also define char16, which string16 is based upon.
|
||||
//
|
||||
// WHY:
|
||||
// On Windows, wchar_t is 2 bytes, and it can conveniently handle UTF-16/UCS-2
|
||||
// data. Plenty of existing code operates on strings encoded as UTF-16.
|
||||
//
|
||||
// On many other platforms, sizeof(wchar_t) is 4 bytes by default. We can make
|
||||
// it 2 bytes by using the GCC flag -fshort-wchar. But then std::wstring fails
|
||||
// at run time, because it calls some functions (like wcslen) that come from
|
||||
// the system's native C library -- which was built with a 4-byte wchar_t!
|
||||
// It's wasteful to use 4-byte wchar_t strings to carry UTF-16 data, and it's
|
||||
// entirely improper on those systems where the encoding of wchar_t is defined
|
||||
// as UTF-32.
|
||||
//
|
||||
// Here, we define string16, which is similar to std::wstring but replaces all
|
||||
// libc functions with custom, 2-byte-char compatible routines. It is capable
|
||||
// of carrying UTF-16-encoded data.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
|
||||
#if defined(WCHAR_T_IS_UTF16)
|
||||
|
||||
namespace base {
|
||||
|
||||
typedef wchar_t char16;
|
||||
typedef std::wstring string16;
|
||||
typedef std::char_traits<wchar_t> string16_char_traits;
|
||||
|
||||
} // namespace base
|
||||
|
||||
#elif defined(WCHAR_T_IS_UTF32)
|
||||
|
||||
#include <stdint.h> // For uint16_t
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
typedef uint16_t char16;
|
||||
|
||||
// char16 versions of the functions required by string16_char_traits; these
|
||||
// are based on the wide character functions of similar names ("w" or "wcs"
|
||||
// instead of "c16").
|
||||
int c16memcmp(const char16* s1, const char16* s2, size_t n);
|
||||
size_t c16len(const char16* s);
|
||||
const char16* c16memchr(const char16* s, char16 c, size_t n);
|
||||
char16* c16memmove(char16* s1, const char16* s2, size_t n);
|
||||
char16* c16memcpy(char16* s1, const char16* s2, size_t n);
|
||||
char16* c16memset(char16* s, char16 c, size_t n);
|
||||
|
||||
struct string16_char_traits {
|
||||
typedef char16 char_type;
|
||||
typedef int int_type;
|
||||
|
||||
// int_type needs to be able to hold each possible value of char_type, and in
|
||||
// addition, the distinct value of eof().
|
||||
COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width);
|
||||
|
||||
typedef std::streamoff off_type;
|
||||
typedef mbstate_t state_type;
|
||||
typedef std::fpos<state_type> pos_type;
|
||||
|
||||
static void assign(char_type& c1, const char_type& c2) {
|
||||
c1 = c2;
|
||||
}
|
||||
|
||||
static bool eq(const char_type& c1, const char_type& c2) {
|
||||
return c1 == c2;
|
||||
}
|
||||
static bool lt(const char_type& c1, const char_type& c2) {
|
||||
return c1 < c2;
|
||||
}
|
||||
|
||||
static int compare(const char_type* s1, const char_type* s2, size_t n) {
|
||||
return c16memcmp(s1, s2, n);
|
||||
}
|
||||
|
||||
static size_t length(const char_type* s) {
|
||||
return c16len(s);
|
||||
}
|
||||
|
||||
static const char_type* find(const char_type* s, size_t n,
|
||||
const char_type& a) {
|
||||
return c16memchr(s, a, n);
|
||||
}
|
||||
|
||||
static char_type* move(char_type* s1, const char_type* s2, int_type n) {
|
||||
return c16memmove(s1, s2, n);
|
||||
}
|
||||
|
||||
static char_type* copy(char_type* s1, const char_type* s2, size_t n) {
|
||||
return c16memcpy(s1, s2, n);
|
||||
}
|
||||
|
||||
static char_type* assign(char_type* s, size_t n, char_type a) {
|
||||
return c16memset(s, a, n);
|
||||
}
|
||||
|
||||
static int_type not_eof(const int_type& c) {
|
||||
return eq_int_type(c, eof()) ? 0 : c;
|
||||
}
|
||||
|
||||
static char_type to_char_type(const int_type& c) {
|
||||
return char_type(c);
|
||||
}
|
||||
|
||||
static int_type to_int_type(const char_type& c) {
|
||||
return int_type(c);
|
||||
}
|
||||
|
||||
static bool eq_int_type(const int_type& c1, const int_type& c2) {
|
||||
return c1 == c2;
|
||||
}
|
||||
|
||||
static int_type eof() {
|
||||
return static_cast<int_type>(EOF);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::basic_string<char16, base::string16_char_traits> string16;
|
||||
|
||||
extern std::ostream& operator<<(std::ostream& out, const string16& str);
|
||||
|
||||
// This is required by googletest to print a readable output on test failures.
|
||||
extern void PrintTo(const string16& str, std::ostream* out);
|
||||
|
||||
} // namespace base
|
||||
|
||||
// The string class will be explicitly instantiated only once, in string16.cc.
|
||||
//
|
||||
// std::basic_string<> in GNU libstdc++ contains a static data member,
|
||||
// _S_empty_rep_storage, to represent empty strings. When an operation such
|
||||
// as assignment or destruction is performed on a string, causing its existing
|
||||
// data member to be invalidated, it must not be freed if this static data
|
||||
// member is being used. Otherwise, it counts as an attempt to free static
|
||||
// (and not allocated) data, which is a memory error.
|
||||
//
|
||||
// Generally, due to C++ template magic, _S_empty_rep_storage will be marked
|
||||
// as a coalesced symbol, meaning that the linker will combine multiple
|
||||
// instances into a single one when generating output.
|
||||
//
|
||||
// If a string class is used by multiple shared libraries, a problem occurs.
|
||||
// Each library will get its own copy of _S_empty_rep_storage. When strings
|
||||
// are passed across a library boundary for alteration or destruction, memory
|
||||
// errors will result. GNU libstdc++ contains a configuration option,
|
||||
// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which
|
||||
// disables the static data member optimization, but it's a good optimization
|
||||
// and non-STL code is generally at the mercy of the system's STL
|
||||
// configuration. Fully-dynamic strings are not the default for GNU libstdc++
|
||||
// libstdc++ itself or for the libstdc++ installations on the systems we care
|
||||
// about, such as Mac OS X and relevant flavors of Linux.
|
||||
//
|
||||
// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 .
|
||||
//
|
||||
// To avoid problems, string classes need to be explicitly instantiated only
|
||||
// once, in exactly one library. All other string users see it via an "extern"
|
||||
// declaration. This is precisely how GNU libstdc++ handles
|
||||
// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring).
|
||||
//
|
||||
// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2),
|
||||
// in which the linker does not fully coalesce symbols when dead code
|
||||
// stripping is enabled. This bug causes the memory errors described above
|
||||
// to occur even when a std::basic_string<> does not cross shared library
|
||||
// boundaries, such as in statically-linked executables.
|
||||
//
|
||||
// TODO(mark): File this bug with Apple and update this note with a bug number.
|
||||
|
||||
extern template
|
||||
class std::basic_string<base::char16, base::string16_char_traits>;
|
||||
|
||||
#endif // WCHAR_T_IS_UTF32
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_STRING16_H_
|
192
include/base/cef_template_util.h
Normal file
192
include/base/cef_template_util.h
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_TEMPLATE_UTIL_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/template_util.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <cstddef> // For size_t.
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// template definitions from tr1
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
template <class T> struct is_pointer : false_type {};
|
||||
template <class T> struct is_pointer<T*> : true_type {};
|
||||
|
||||
// Member function pointer detection up to four params. Add more as needed
|
||||
// below. This is built-in to C++ 11, and we can remove this when we switch.
|
||||
template<typename T>
|
||||
struct is_member_function_pointer : false_type {};
|
||||
|
||||
template <typename R, typename Z>
|
||||
struct is_member_function_pointer<R(Z::*)()> : true_type {};
|
||||
template <typename R, typename Z>
|
||||
struct is_member_function_pointer<R(Z::*)() const> : true_type {};
|
||||
|
||||
template <typename R, typename Z, typename A>
|
||||
struct is_member_function_pointer<R(Z::*)(A)> : true_type {};
|
||||
template <typename R, typename Z, typename A>
|
||||
struct is_member_function_pointer<R(Z::*)(A) const> : true_type {};
|
||||
|
||||
template <typename R, typename Z, typename A, typename B>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B)> : true_type {};
|
||||
template <typename R, typename Z, typename A, typename B>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B) const> : true_type {};
|
||||
|
||||
template <typename R, typename Z, typename A, typename B, typename C>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B, C)> : true_type {};
|
||||
template <typename R, typename Z, typename A, typename B, typename C>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B, C) const> : true_type {};
|
||||
|
||||
template <typename R, typename Z, typename A, typename B, typename C,
|
||||
typename D>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B, C, D)> : true_type {};
|
||||
template <typename R, typename Z, typename A, typename B, typename C,
|
||||
typename D>
|
||||
struct is_member_function_pointer<R(Z::*)(A, B, C, D) const> : true_type {};
|
||||
|
||||
|
||||
template <class T, class U> struct is_same : public false_type {};
|
||||
template <class T> struct is_same<T,T> : true_type {};
|
||||
|
||||
template<class> struct is_array : public false_type {};
|
||||
template<class T, size_t n> struct is_array<T[n]> : public true_type {};
|
||||
template<class T> struct is_array<T[]> : public true_type {};
|
||||
|
||||
template <class T> struct is_non_const_reference : false_type {};
|
||||
template <class T> struct is_non_const_reference<T&> : true_type {};
|
||||
template <class T> struct is_non_const_reference<const T&> : false_type {};
|
||||
|
||||
template <class T> struct is_const : false_type {};
|
||||
template <class T> struct is_const<const T> : true_type {};
|
||||
|
||||
template <class T> struct is_void : false_type {};
|
||||
template <> struct is_void<void> : true_type {};
|
||||
|
||||
namespace cef_internal {
|
||||
|
||||
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
|
||||
// sizeof(NoType).
|
||||
typedef char YesType;
|
||||
|
||||
struct NoType {
|
||||
YesType dummy[2];
|
||||
};
|
||||
|
||||
// This class is an implementation detail for is_convertible, and you
|
||||
// don't need to know how it works to use is_convertible. For those
|
||||
// who care: we declare two different functions, one whose argument is
|
||||
// of type To and one with a variadic argument list. We give them
|
||||
// return types of different size, so we can use sizeof to trick the
|
||||
// compiler into telling us which function it would have chosen if we
|
||||
// had called it with an argument of type From. See Alexandrescu's
|
||||
// _Modern C++ Design_ for more details on this sort of trick.
|
||||
|
||||
struct ConvertHelper {
|
||||
template <typename To>
|
||||
static YesType Test(To);
|
||||
|
||||
template <typename To>
|
||||
static NoType Test(...);
|
||||
|
||||
template <typename From>
|
||||
static From& Create();
|
||||
};
|
||||
|
||||
// Used to determine if a type is a struct/union/class. Inspired by Boost's
|
||||
// is_class type_trait implementation.
|
||||
struct IsClassHelper {
|
||||
template <typename C>
|
||||
static YesType Test(void(C::*)(void));
|
||||
|
||||
template <typename C>
|
||||
static NoType Test(...);
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||
//
|
||||
// Note that if the type is convertible, this will be a true_type REGARDLESS
|
||||
// of whether or not the conversion would emit a warning.
|
||||
template <typename From, typename To>
|
||||
struct is_convertible
|
||||
: integral_constant<bool,
|
||||
sizeof(cef_internal::ConvertHelper::Test<To>(
|
||||
cef_internal::ConvertHelper::Create<From>())) ==
|
||||
sizeof(cef_internal::YesType)> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_class
|
||||
: integral_constant<bool,
|
||||
sizeof(cef_internal::IsClassHelper::Test<T>(0)) ==
|
||||
sizeof(cef_internal::YesType)> {
|
||||
};
|
||||
|
||||
template<bool B, class T = void>
|
||||
struct enable_if {};
|
||||
|
||||
template<class T>
|
||||
struct enable_if<true, T> { typedef T type; };
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
|
125
include/base/cef_thread_checker.h
Normal file
125
include/base/cef_thread_checker.h
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_THREAD_CHECKER_H_
|
||||
#define CEF_INCLUDE_BASE_THREAD_CHECKER_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_THREADING_THREAD_CHECKER_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/threading/thread_checker.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
// Apart from debug builds, we also enable the thread checker in
|
||||
// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
|
||||
// with this define will get the same level of thread checking as
|
||||
// debug bots.
|
||||
//
|
||||
// Note that this does not perfectly match situations where DCHECK is
|
||||
// enabled. For example a non-official release build may have
|
||||
// DCHECK_ALWAYS_ON undefined (and therefore ThreadChecker would be
|
||||
// disabled) but have DCHECKs enabled at runtime.
|
||||
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
|
||||
#define ENABLE_THREAD_CHECKER 1
|
||||
#else
|
||||
#define ENABLE_THREAD_CHECKER 0
|
||||
#endif
|
||||
|
||||
#include "include/base/internal/cef_thread_checker_impl.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// 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.
|
||||
class ThreadCheckerDoNothing {
|
||||
public:
|
||||
bool CalledOnValidThread() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DetachFromThread() {}
|
||||
};
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// guide with regard to multiple inheritance. The choice between having a
|
||||
// ThreadChecker member and inheriting from base::NonThreadSafe should be based
|
||||
// on whether:
|
||||
// - Derived classes need to know the thread they belong to, as opposed to
|
||||
// having that functionality fully encapsulated in the base class.
|
||||
// - 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.
|
||||
//
|
||||
// Example:
|
||||
// class MyClass {
|
||||
// public:
|
||||
// void Foo() {
|
||||
// DCHECK(thread_checker_.CalledOnValidThread());
|
||||
// ... (do stuff) ...
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// ThreadChecker thread_checker_;
|
||||
// }
|
||||
//
|
||||
// In Release mode, CalledOnValidThread will always return true.
|
||||
#if ENABLE_THREAD_CHECKER
|
||||
class ThreadChecker : public ThreadCheckerImpl {
|
||||
};
|
||||
#else
|
||||
class ThreadChecker : public ThreadCheckerDoNothing {
|
||||
};
|
||||
#endif // ENABLE_THREAD_CHECKER
|
||||
|
||||
#undef ENABLE_THREAD_CHECKER
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_THREAD_CHECKER_H_
|
287
include/base/cef_thread_collision_warner.h
Normal file
287
include/base/cef_thread_collision_warner.h
Normal file
@ -0,0 +1,287 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_THREAD_COLLISION_WARNER_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_THREAD_COLLISION_WARNER_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_THREADING_THREAD_COLLISION_WARNER_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/threading/thread_collision_warner.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "include/base/cef_atomicops.h"
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
// A helper class alongside macros to be used to verify assumptions about thread
|
||||
// safety of a class.
|
||||
//
|
||||
// Example: Queue implementation non thread-safe but still usable if clients
|
||||
// are synchronized somehow.
|
||||
//
|
||||
// In this case the macro DFAKE_SCOPED_LOCK has to be
|
||||
// used, it checks that if a thread is inside the push/pop then
|
||||
// noone else is still inside the pop/push
|
||||
//
|
||||
// class NonThreadSafeQueue {
|
||||
// public:
|
||||
// ...
|
||||
// void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
|
||||
// int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
|
||||
// ...
|
||||
// private:
|
||||
// DFAKE_MUTEX(push_pop_);
|
||||
// };
|
||||
//
|
||||
//
|
||||
// Example: Queue implementation non thread-safe but still usable if clients
|
||||
// are synchronized somehow, it calls a method to "protect" from
|
||||
// a "protected" method
|
||||
//
|
||||
// In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK
|
||||
// has to be used, it checks that if a thread is inside the push/pop
|
||||
// then noone else is still inside the pop/push
|
||||
//
|
||||
// class NonThreadSafeQueue {
|
||||
// public:
|
||||
// void push(int) {
|
||||
// DFAKE_SCOPED_LOCK(push_pop_);
|
||||
// ...
|
||||
// }
|
||||
// int pop() {
|
||||
// DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
|
||||
// bar();
|
||||
// ...
|
||||
// }
|
||||
// void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... }
|
||||
// ...
|
||||
// private:
|
||||
// DFAKE_MUTEX(push_pop_);
|
||||
// };
|
||||
//
|
||||
//
|
||||
// Example: Queue implementation not usable even if clients are synchronized,
|
||||
// so only one thread in the class life cycle can use the two members
|
||||
// push/pop.
|
||||
//
|
||||
// In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
|
||||
// specified
|
||||
// critical section the first time a thread enters push or pop, from
|
||||
// that time on only that thread is allowed to execute push or pop.
|
||||
//
|
||||
// class NonThreadSafeQueue {
|
||||
// public:
|
||||
// ...
|
||||
// void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
|
||||
// int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
|
||||
// ...
|
||||
// private:
|
||||
// DFAKE_MUTEX(push_pop_);
|
||||
// };
|
||||
//
|
||||
//
|
||||
// Example: Class that has to be contructed/destroyed on same thread, it has
|
||||
// a "shareable" method (with external synchronization) and a not
|
||||
// shareable method (even with external synchronization).
|
||||
//
|
||||
// In this case 3 Critical sections have to be defined
|
||||
//
|
||||
// class ExoticClass {
|
||||
// public:
|
||||
// ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
||||
// ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
||||
//
|
||||
// void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
|
||||
// void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
|
||||
// ...
|
||||
// private:
|
||||
// DFAKE_MUTEX(ctor_dtor_);
|
||||
// DFAKE_MUTEX(shareable_section_);
|
||||
// };
|
||||
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
// Defines a class member that acts like a mutex. It is used only as a
|
||||
// verification tool.
|
||||
#define DFAKE_MUTEX(obj) \
|
||||
mutable base::ThreadCollisionWarner obj
|
||||
// Asserts the call is never called simultaneously in two threads. Used at
|
||||
// member function scope.
|
||||
#define DFAKE_SCOPED_LOCK(obj) \
|
||||
base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj)
|
||||
// Asserts the call is never called simultaneously in two threads. Used at
|
||||
// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks.
|
||||
#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \
|
||||
base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj)
|
||||
// Asserts the code is always executed in the same thread.
|
||||
#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \
|
||||
base::ThreadCollisionWarner::Check check_##obj(&obj)
|
||||
|
||||
#else
|
||||
|
||||
#define DFAKE_MUTEX(obj) typedef void InternalFakeMutexType##obj
|
||||
#define DFAKE_SCOPED_LOCK(obj) ((void)0)
|
||||
#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0)
|
||||
#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
|
||||
// The class ThreadCollisionWarner uses an Asserter to notify the collision
|
||||
// AsserterBase is the interfaces and DCheckAsserter is the default asserter
|
||||
// used. During the unit tests is used another class that doesn't "DCHECK"
|
||||
// in case of collision (check thread_collision_warner_unittests.cc)
|
||||
struct AsserterBase {
|
||||
virtual ~AsserterBase() {}
|
||||
virtual void warn() = 0;
|
||||
};
|
||||
|
||||
struct DCheckAsserter : public AsserterBase {
|
||||
virtual ~DCheckAsserter() {}
|
||||
virtual void warn() OVERRIDE;
|
||||
};
|
||||
|
||||
class ThreadCollisionWarner {
|
||||
public:
|
||||
// The parameter asserter is there only for test purpose
|
||||
explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
|
||||
: valid_thread_id_(0),
|
||||
counter_(0),
|
||||
asserter_(asserter) {}
|
||||
|
||||
~ThreadCollisionWarner() {
|
||||
delete asserter_;
|
||||
}
|
||||
|
||||
// This class is meant to be used through the macro
|
||||
// DFAKE_SCOPED_LOCK_THREAD_LOCKED
|
||||
// it doesn't leave the critical section, as opposed to ScopedCheck,
|
||||
// because the critical section being pinned is allowed to be used only
|
||||
// from one thread
|
||||
class Check {
|
||||
public:
|
||||
explicit Check(ThreadCollisionWarner* warner)
|
||||
: warner_(warner) {
|
||||
warner_->EnterSelf();
|
||||
}
|
||||
|
||||
~Check() {}
|
||||
|
||||
private:
|
||||
ThreadCollisionWarner* warner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Check);
|
||||
};
|
||||
|
||||
// This class is meant to be used through the macro
|
||||
// DFAKE_SCOPED_LOCK
|
||||
class ScopedCheck {
|
||||
public:
|
||||
explicit ScopedCheck(ThreadCollisionWarner* warner)
|
||||
: warner_(warner) {
|
||||
warner_->Enter();
|
||||
}
|
||||
|
||||
~ScopedCheck() {
|
||||
warner_->Leave();
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadCollisionWarner* warner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
|
||||
};
|
||||
|
||||
// This class is meant to be used through the macro
|
||||
// DFAKE_SCOPED_RECURSIVE_LOCK
|
||||
class ScopedRecursiveCheck {
|
||||
public:
|
||||
explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner)
|
||||
: warner_(warner) {
|
||||
warner_->EnterSelf();
|
||||
}
|
||||
|
||||
~ScopedRecursiveCheck() {
|
||||
warner_->Leave();
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadCollisionWarner* warner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck);
|
||||
};
|
||||
|
||||
private:
|
||||
// This method stores the current thread identifier and does a DCHECK
|
||||
// if a another thread has already done it, it is safe if same thread
|
||||
// calls this multiple time (recursion allowed).
|
||||
void EnterSelf();
|
||||
|
||||
// Same as EnterSelf but recursion is not allowed.
|
||||
void Enter();
|
||||
|
||||
// Removes the thread_id stored in order to allow other threads to
|
||||
// call EnterSelf or Enter.
|
||||
void Leave();
|
||||
|
||||
// This stores the thread id that is inside the critical section, if the
|
||||
// value is 0 then no thread is inside.
|
||||
volatile subtle::Atomic32 valid_thread_id_;
|
||||
|
||||
// Counter to trace how many time a critical section was "pinned"
|
||||
// (when allowed) in order to unpin it when counter_ reaches 0.
|
||||
volatile subtle::Atomic32 counter_;
|
||||
|
||||
// Here only for class unit tests purpose, during the test I need to not
|
||||
// DCHECK but notify the collision with something else.
|
||||
AsserterBase* asserter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner);
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_THREAD_COLLISION_WARNER_H_
|
427
include/base/cef_trace_event.h
Normal file
427
include/base/cef_trace_event.h
Normal file
@ -0,0 +1,427 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
///
|
||||
// Trace events are for tracking application performance and resource usage.
|
||||
// Macros are provided to track:
|
||||
// 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:
|
||||
// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
|
||||
//
|
||||
// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
|
||||
// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
|
||||
// doSomethingCostly()
|
||||
// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
|
||||
// Note: Our tools can't always determine the correct BEGIN/END pairs unless
|
||||
// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
|
||||
// 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:
|
||||
// void doSomethingCostly() {
|
||||
// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Additional parameters can be associated with an event:
|
||||
// void doSomethingCostly2(int howMuch) {
|
||||
// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
|
||||
// "howMuch", howMuch);
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The trace system will automatically add to this information the current
|
||||
// process id, thread id, and a timestamp in microseconds.
|
||||
//
|
||||
// To trace an asynchronous procedure such as an IPC send/receive, use
|
||||
// ASYNC_BEGIN and ASYNC_END:
|
||||
// [single threaded sender code]
|
||||
// static int send_count = 0;
|
||||
// ++send_count;
|
||||
// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
|
||||
// Send(new MyMessage(send_count));
|
||||
// [receive code]
|
||||
// void OnMyMessage(send_count) {
|
||||
// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
|
||||
// }
|
||||
// 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
|
||||
// match. For example:
|
||||
// class MyTracedClass {
|
||||
// public:
|
||||
// MyTracedClass() {
|
||||
// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
|
||||
// }
|
||||
// ~MyTracedClass() {
|
||||
// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// The trace event also supports counters, which is a way to track a quantity
|
||||
// as it varies over time. Counters are created with the following macro:
|
||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
|
||||
//
|
||||
// Counters are process-specific. The macro itself can be issued from any
|
||||
// thread, however.
|
||||
//
|
||||
// Sometimes, you want to track two counters at once. You can do this with two
|
||||
// counter macros:
|
||||
// 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:
|
||||
// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
|
||||
// "bytesPinned", g_myCounterValue[0],
|
||||
// "bytesAllocated", g_myCounterValue[1]);
|
||||
// This indicates to the tracing UI that these counters should be displayed
|
||||
// in a single graph, as a summed area chart.
|
||||
//
|
||||
// Since counters are in a global namespace, you may want to disembiguate with a
|
||||
// unique ID, by using the TRACE_COUNTER_ID* variations.
|
||||
//
|
||||
// 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
|
||||
// processes.
|
||||
//
|
||||
//
|
||||
// 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:
|
||||
// char* str = strdup("impprtantName");
|
||||
// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
|
||||
// free(str); // Trace system now has dangling pointer
|
||||
//
|
||||
// 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_
|
||||
#define CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(TRACE_EVENT0)
|
||||
// Do nothing if the macros provided by this header already exist.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/debug/trace_event.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#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
|
||||
// enabled, then this does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT0(category, name) \
|
||||
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \
|
||||
CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
|
||||
#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false); \
|
||||
CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
|
||||
#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val, false); \
|
||||
CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
|
||||
|
||||
// Implementation detail: trace event macros create temporary variable names.
|
||||
// These macros give each temporary variable a unique name based on the line
|
||||
// number to prevent name collisions.
|
||||
#define CEF_INTERNAL_TRACE_EVENT_UID3(a,b) \
|
||||
cef_trace_event_unique_##a##b
|
||||
#define CEF_INTERNAL_TRACE_EVENT_UID2(a,b) \
|
||||
CEF_INTERNAL_TRACE_EVENT_UID3(a,b)
|
||||
#define CEF_INTERNAL_TRACE_EVENT_UID(name_prefix) \
|
||||
CEF_INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
|
||||
|
||||
// Implementation detail: internal macro to end end event when the scope ends.
|
||||
#define CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) \
|
||||
cef_trace_event::CefTraceEndOnScopeClose \
|
||||
CEF_INTERNAL_TRACE_EVENT_UID(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
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_INSTANT0(category, name) \
|
||||
cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false)
|
||||
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false)
|
||||
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val, false)
|
||||
#define TRACE_EVENT_COPY_INSTANT0(category, name) \
|
||||
cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
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
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_BEGIN0(category, name) \
|
||||
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false)
|
||||
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false)
|
||||
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val, false)
|
||||
#define TRACE_EVENT_COPY_BEGIN0(category, name) \
|
||||
cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val, true)
|
||||
|
||||
// Records a single END event for "name" immediately. If the category
|
||||
// is not enabled, then this does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_END0(category, name) \
|
||||
cef_trace_event_end(category, name, NULL, 0, NULL, 0, false)
|
||||
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false)
|
||||
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val, false)
|
||||
#define TRACE_EVENT_COPY_END0(category, name) \
|
||||
cef_trace_event_end(category, name, NULL, 0, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
|
||||
cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \
|
||||
arg2_val, true)
|
||||
|
||||
// Records the value of a counter called "name" immediately. Value
|
||||
// must be representable as a 32 bit integer.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_COUNTER1(category, name, value) \
|
||||
cef_trace_counter(category, name, NULL, value, NULL, 0, false)
|
||||
#define TRACE_COPY_COUNTER1(category, name, value) \
|
||||
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
|
||||
// values as a stacked-bar chart.
|
||||
// - 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, value2_val) \
|
||||
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
||||
value2_val, false)
|
||||
#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
|
||||
value2_name, value2_val) \
|
||||
cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
|
||||
value2_val, true)
|
||||
|
||||
// Records the value of a counter called "name" immediately. Value
|
||||
// must be representable as a 32 bit integer.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to disambiguate counters with the same name. It must either
|
||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
||||
// 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) \
|
||||
cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false)
|
||||
#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
|
||||
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
|
||||
// values as a stacked-bar chart.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to disambiguate counters with the same name. It must either
|
||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the
|
||||
// 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, \
|
||||
value2_name, value2_val) \
|
||||
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
||||
value2_name, value2_val, false)
|
||||
#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, \
|
||||
value1_val, value2_name, value2_val) \
|
||||
cef_trace_counter_id(category, name, id, value1_name, value1_val, \
|
||||
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
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
|
||||
// ASYNC events are considered to match if their category, name and id values
|
||||
// all match. |id| must either be a pointer or an integer value up to 64
|
||||
// bits. If it's a pointer, the bits will be xored with a hash of the process
|
||||
// ID sothat the same pointer on two different processes will not collide.
|
||||
// An asynchronous operation can consist of multiple phases. The first phase is
|
||||
// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
|
||||
// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
|
||||
// An async operation can span threads and processes, but all events in that
|
||||
// operation must use the same |name| and |id|. Each event can have its own
|
||||
// args.
|
||||
#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
|
||||
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) \
|
||||
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \
|
||||
0, false)
|
||||
#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val, false)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
|
||||
cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, \
|
||||
arg1_val) \
|
||||
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \
|
||||
0, true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, \
|
||||
arg1_val, arg2_name, arg2_val) \
|
||||
cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \
|
||||
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
|
||||
// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
||||
// within the async event. This should be called at the beginning of the next
|
||||
// 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) \
|
||||
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, arg1_val) \
|
||||
cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
|
||||
arg1_val, false)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \
|
||||
cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
cef_trace_event_async_step_into(category, name, id, step, arg1_name, \
|
||||
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
|
||||
// match the ASYNC_BEGIN event above. The |step| param identifies this step
|
||||
// within the async event. This should be called at the beginning of the next
|
||||
// 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) \
|
||||
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, arg1_val) \
|
||||
cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
|
||||
arg1_val, false)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \
|
||||
cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
cef_trace_event_async_step_past(category, name, id, step, arg1_name, \
|
||||
arg1_val, true)
|
||||
|
||||
// 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) \
|
||||
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) \
|
||||
cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
|
||||
false)
|
||||
#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val, false)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
|
||||
cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, \
|
||||
arg1_val) \
|
||||
cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
|
||||
true)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, \
|
||||
arg1_val, arg2_name, arg2_val) \
|
||||
cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val, true)
|
||||
|
||||
namespace cef_trace_event {
|
||||
|
||||
// Used by TRACE_EVENTx macro. Do not use directly.
|
||||
class CefTraceEndOnScopeClose {
|
||||
public:
|
||||
CefTraceEndOnScopeClose(const char* category, const char* name)
|
||||
: category_(category), name_(name) {
|
||||
}
|
||||
~CefTraceEndOnScopeClose() {
|
||||
cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* category_;
|
||||
const char* name_;
|
||||
};
|
||||
|
||||
} // cef_trace_event
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
|
1399
include/base/cef_tuple.h
Normal file
1399
include/base/cef_tuple.h
Normal file
File diff suppressed because it is too large
Load Diff
382
include/base/cef_weak_ptr.h
Normal file
382
include/base/cef_weak_ptr.h
Normal file
@ -0,0 +1,382 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// 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 NULL) by the object, or its
|
||||
// owner, at any time, most commonly when the object is about to be deleted.
|
||||
|
||||
// Weak pointers are useful when an object needs to be accessed safely by one
|
||||
// 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.
|
||||
// Reference-counting such an object would complicate the ownership graph and
|
||||
// make it harder to reason about the object's lifetime.
|
||||
|
||||
// EXAMPLE:
|
||||
//
|
||||
// class Controller {
|
||||
// public:
|
||||
// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
|
||||
// void WorkComplete(const Result& result) { ... }
|
||||
// private:
|
||||
// // 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.
|
||||
// WeakPtrFactory<Controller> weak_factory_;
|
||||
// };
|
||||
//
|
||||
// class Worker {
|
||||
// public:
|
||||
// static void StartNew(const WeakPtr<Controller>& controller) {
|
||||
// Worker* worker = new Worker(controller);
|
||||
// // Kick off asynchronous processing...
|
||||
// }
|
||||
// private:
|
||||
// Worker(const WeakPtr<Controller>& controller)
|
||||
// : controller_(controller) {}
|
||||
// void DidCompleteAsynchronousProcessing(const Result& result) {
|
||||
// if (controller_)
|
||||
// controller_->WorkComplete(result);
|
||||
// }
|
||||
// WeakPtr<Controller> controller_;
|
||||
// };
|
||||
//
|
||||
// With this implementation a caller may use SpawnWorker() to dispatch multiple
|
||||
// Workers and subsequently delete the Controller, without waiting for all
|
||||
// Workers to have completed.
|
||||
|
||||
// ------------------------- IMPORTANT: Thread-safety -------------------------
|
||||
|
||||
// Weak pointers may be passed safely between threads, but must always be
|
||||
// dereferenced and invalidated on the same thread otherwise checking the
|
||||
// pointer would be racey.
|
||||
//
|
||||
// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
|
||||
// is dereferenced, the factory and its WeakPtrs become bound to the calling
|
||||
// thread, and cannot be dereferenced or invalidated on any other thread. Bound
|
||||
// WeakPtrs can still be handed off to other threads, e.g. to use to post tasks
|
||||
// back to object on the bound thread.
|
||||
//
|
||||
// Invalidating the factory's WeakPtrs un-binds it from the thread, allowing it
|
||||
// to be passed for a different thread to use or delete it.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_MEMORY_WEAK_PTR_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_basictypes.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/base/cef_template_util.h"
|
||||
#include "include/base/cef_thread_checker.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename T> class SupportsWeakPtr;
|
||||
template <typename T> class WeakPtr;
|
||||
|
||||
namespace cef_internal {
|
||||
// These classes are part of the WeakPtr implementation.
|
||||
// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
|
||||
|
||||
class WeakReference {
|
||||
public:
|
||||
// Although Flag is bound to a specific thread, it may be deleted from another
|
||||
// via base::WeakPtr::~WeakPtr().
|
||||
class Flag : public RefCountedThreadSafe<Flag> {
|
||||
public:
|
||||
Flag();
|
||||
|
||||
void Invalidate();
|
||||
bool IsValid() const;
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<Flag>;
|
||||
|
||||
~Flag();
|
||||
|
||||
// The current Chromium implementation uses SequenceChecker instead of
|
||||
// ThreadChecker to support SequencedWorkerPools. CEF does not yet expose
|
||||
// the concept of SequencedWorkerPools.
|
||||
ThreadChecker thread_checker_;
|
||||
bool is_valid_;
|
||||
};
|
||||
|
||||
WeakReference();
|
||||
explicit WeakReference(const Flag* flag);
|
||||
~WeakReference();
|
||||
|
||||
bool is_valid() const;
|
||||
|
||||
private:
|
||||
scoped_refptr<const Flag> flag_;
|
||||
};
|
||||
|
||||
class WeakReferenceOwner {
|
||||
public:
|
||||
WeakReferenceOwner();
|
||||
~WeakReferenceOwner();
|
||||
|
||||
WeakReference GetRef() const;
|
||||
|
||||
bool HasRefs() const {
|
||||
return flag_.get() && !flag_->HasOneRef();
|
||||
}
|
||||
|
||||
void Invalidate();
|
||||
|
||||
private:
|
||||
mutable scoped_refptr<WeakReference::Flag> flag_;
|
||||
};
|
||||
|
||||
// This class simplifies the implementation of WeakPtr's type conversion
|
||||
// constructor by avoiding the need for a public accessor for ref_. A
|
||||
// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
|
||||
// base class gives us a way to access ref_ in a protected fashion.
|
||||
class WeakPtrBase {
|
||||
public:
|
||||
WeakPtrBase();
|
||||
~WeakPtrBase();
|
||||
|
||||
protected:
|
||||
explicit WeakPtrBase(const WeakReference& ref);
|
||||
|
||||
WeakReference ref_;
|
||||
};
|
||||
|
||||
// This class provides a common implementation of common functions that would
|
||||
// otherwise get instantiated separately for each distinct instantiation of
|
||||
// SupportsWeakPtr<>.
|
||||
class SupportsWeakPtrBase {
|
||||
public:
|
||||
// A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
|
||||
// conversion will only compile if there is exists a Base which inherits
|
||||
// from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
|
||||
// function that makes calling this easier.
|
||||
template<typename Derived>
|
||||
static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
|
||||
typedef
|
||||
is_convertible<Derived, cef_internal::SupportsWeakPtrBase&> convertible;
|
||||
COMPILE_ASSERT(convertible::value,
|
||||
AsWeakPtr_argument_inherits_from_SupportsWeakPtr);
|
||||
return AsWeakPtrImpl<Derived>(t, *t);
|
||||
}
|
||||
|
||||
private:
|
||||
// This template function uses type inference to find a Base of Derived
|
||||
// which is an instance of SupportsWeakPtr<Base>. We can then safely
|
||||
// static_cast the Base* to a Derived*.
|
||||
template <typename Derived, typename Base>
|
||||
static WeakPtr<Derived> AsWeakPtrImpl(
|
||||
Derived* t, const SupportsWeakPtr<Base>&) {
|
||||
WeakPtr<Base> ptr = t->Base::AsWeakPtr();
|
||||
return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
template <typename T> class WeakPtrFactory;
|
||||
|
||||
// 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
|
||||
// may result in the underlying object being destroyed.
|
||||
//
|
||||
// EXAMPLE:
|
||||
//
|
||||
// class Foo { ... };
|
||||
// WeakPtr<Foo> foo;
|
||||
// if (foo)
|
||||
// foo->method();
|
||||
//
|
||||
template <typename T>
|
||||
class WeakPtr : public cef_internal::WeakPtrBase {
|
||||
public:
|
||||
WeakPtr() : ptr_(NULL) {
|
||||
}
|
||||
|
||||
// Allow conversion from U to T provided U "is a" T. Note that this
|
||||
// is separate from the (implicit) copy constructor.
|
||||
template <typename U>
|
||||
WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) {
|
||||
}
|
||||
|
||||
T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
|
||||
|
||||
T& operator*() const {
|
||||
DCHECK(get() != NULL);
|
||||
return *get();
|
||||
}
|
||||
T* operator->() const {
|
||||
DCHECK(get() != NULL);
|
||||
return get();
|
||||
}
|
||||
|
||||
// Allow WeakPtr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
//
|
||||
// Note that this trick is only safe when the == and != operators
|
||||
// are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2"
|
||||
// will compile but do the wrong thing (i.e., convert to Testable
|
||||
// and then do the comparison).
|
||||
private:
|
||||
typedef T* WeakPtr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; }
|
||||
|
||||
void reset() {
|
||||
ref_ = cef_internal::WeakReference();
|
||||
ptr_ = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
// Explicitly declare comparison operators as required by the bool
|
||||
// trick, but keep them private.
|
||||
template <class U> bool operator==(WeakPtr<U> const&) const;
|
||||
template <class U> bool operator!=(WeakPtr<U> const&) const;
|
||||
|
||||
friend class cef_internal::SupportsWeakPtrBase;
|
||||
template <typename U> friend class WeakPtr;
|
||||
friend class SupportsWeakPtr<T>;
|
||||
friend class WeakPtrFactory<T>;
|
||||
|
||||
WeakPtr(const cef_internal::WeakReference& ref, T* ptr)
|
||||
: WeakPtrBase(ref),
|
||||
ptr_(ptr) {
|
||||
}
|
||||
|
||||
// This pointer is only valid when ref_.is_valid() is true. Otherwise, its
|
||||
// value is undefined (as opposed to NULL).
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
// A class may be composed of a WeakPtrFactory and thereby
|
||||
// control how it exposes weak pointers to itself. This is helpful if you only
|
||||
// need weak pointers within the implementation of a class. This class is also
|
||||
// useful 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>
|
||||
class WeakPtrFactory {
|
||||
public:
|
||||
explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
|
||||
}
|
||||
|
||||
~WeakPtrFactory() {
|
||||
ptr_ = NULL;
|
||||
}
|
||||
|
||||
WeakPtr<T> GetWeakPtr() {
|
||||
DCHECK(ptr_);
|
||||
return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
|
||||
}
|
||||
|
||||
// Call this method to invalidate all existing weak pointers.
|
||||
void InvalidateWeakPtrs() {
|
||||
DCHECK(ptr_);
|
||||
weak_reference_owner_.Invalidate();
|
||||
}
|
||||
|
||||
// Call this method to determine if any weak pointers exist.
|
||||
bool HasWeakPtrs() const {
|
||||
DCHECK(ptr_);
|
||||
return weak_reference_owner_.HasRefs();
|
||||
}
|
||||
|
||||
private:
|
||||
cef_internal::WeakReferenceOwner weak_reference_owner_;
|
||||
T* ptr_;
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
|
||||
};
|
||||
|
||||
// A class may extend from SupportsWeakPtr to let others take weak pointers to
|
||||
// it. This avoids the class itself implementing boilerplate to dispense weak
|
||||
// pointers. However, since SupportsWeakPtr's destructor won't invalidate
|
||||
// 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>
|
||||
class SupportsWeakPtr : public cef_internal::SupportsWeakPtrBase {
|
||||
public:
|
||||
SupportsWeakPtr() {}
|
||||
|
||||
WeakPtr<T> AsWeakPtr() {
|
||||
return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
|
||||
}
|
||||
|
||||
protected:
|
||||
~SupportsWeakPtr() {}
|
||||
|
||||
private:
|
||||
cef_internal::WeakReferenceOwner weak_reference_owner_;
|
||||
DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
|
||||
};
|
||||
|
||||
// Helper function that uses type deduction to safely return a WeakPtr<Derived>
|
||||
// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
|
||||
// extends a Base that extends SupportsWeakPtr<Base>.
|
||||
//
|
||||
// EXAMPLE:
|
||||
// class Base : public base::SupportsWeakPtr<Producer> {};
|
||||
// class Derived : public Base {};
|
||||
//
|
||||
// Derived derived;
|
||||
// base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
|
||||
//
|
||||
// Note that the following doesn't work (invalid type conversion) since
|
||||
// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
|
||||
// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
|
||||
// the caller.
|
||||
//
|
||||
// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
|
||||
|
||||
template <typename Derived>
|
||||
WeakPtr<Derived> AsWeakPtr(Derived* t) {
|
||||
return cef_internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
|
126
include/base/internal/cef_atomicops_atomicword_compat.h
Normal file
126
include/base/internal/cef_atomicops_atomicword_compat.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_atomicops.h
|
||||
// instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
|
||||
|
||||
// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32,
|
||||
// which in turn means int. On some LP32 platforms, intptr_t is an int, but
|
||||
// on others, it's a long. When AtomicWord and Atomic32 are based on different
|
||||
// fundamental types, their pointers are incompatible.
|
||||
//
|
||||
// This file defines function overloads to allow both AtomicWord and Atomic32
|
||||
// data to be used with this interface.
|
||||
//
|
||||
// On LP64 platforms, AtomicWord and Atomic64 are both always long,
|
||||
// so this problem doesn't occur.
|
||||
|
||||
#if !defined(ARCH_CPU_64_BITS)
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return NoBarrier_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
|
||||
AtomicWord new_value) {
|
||||
return NoBarrier_AtomicExchange(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
|
||||
AtomicWord increment) {
|
||||
return NoBarrier_AtomicIncrement(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), increment);
|
||||
}
|
||||
|
||||
inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
|
||||
AtomicWord increment) {
|
||||
return Barrier_AtomicIncrement(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), increment);
|
||||
}
|
||||
|
||||
inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return base::subtle::Acquire_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return base::subtle::Release_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
|
||||
NoBarrier_Store(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
|
||||
return base::subtle::Acquire_Store(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
|
||||
return base::subtle::Release_Store(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
|
||||
return NoBarrier_Load(
|
||||
reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
|
||||
return base::subtle::Acquire_Load(
|
||||
reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
|
||||
return base::subtle::Release_Load(
|
||||
reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
} // namespace base::subtle
|
||||
} // namespace base
|
||||
|
||||
#endif // !defined(ARCH_CPU_64_BITS)
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
|
223
include/base/internal/cef_atomicops_mac.h
Normal file
223
include/base/internal/cef_atomicops_mac.h
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright (c) 2012 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_atomicops.h
|
||||
// instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap32(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 old_value;
|
||||
do {
|
||||
old_value = *ptr;
|
||||
} while (!OSAtomicCompareAndSwap32(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr)));
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
OSMemoryBarrier();
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return Acquire_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
MemoryBarrier();
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
|
||||
// 64-bit implementation on 64-bit platform
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap64(old_value, new_value,
|
||||
reinterpret_cast<volatile int64_t*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 old_value;
|
||||
do {
|
||||
old_value = *ptr;
|
||||
} while (!OSAtomicCompareAndSwap64(old_value, new_value,
|
||||
reinterpret_cast<volatile int64_t*>(ptr)));
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return OSAtomicAdd64Barrier(increment,
|
||||
reinterpret_cast<volatile int64_t*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap64Barrier(
|
||||
old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
// The lib kern interface does not distinguish between
|
||||
// Acquire and Release memory barriers; they are equivalent.
|
||||
return Acquire_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
MemoryBarrier();
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr;
|
||||
MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#endif // defined(__LP64__)
|
||||
|
||||
} // namespace base::subtle
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
|
265
include/base/internal/cef_atomicops_x86_gcc.h
Normal file
265
include/base/internal/cef_atomicops_x86_gcc.h
Normal file
@ -0,0 +1,265 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_atomicops.h
|
||||
// instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
|
||||
|
||||
// This struct is not part of the public API of this module; clients may not
|
||||
// use it.
|
||||
// Features of this x86. Values may not be correct before main() is run,
|
||||
// but are set conservatively.
|
||||
struct AtomicOps_x86CPUFeatureStruct {
|
||||
bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
|
||||
// after acquire compare-and-swap.
|
||||
};
|
||||
extern struct AtomicOps_x86CPUFeatureStruct
|
||||
AtomicOps_Internalx86CPUFeatures;
|
||||
|
||||
#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
// 32-bit low-level operations on any platform.
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev;
|
||||
__asm__ __volatile__("lock; cmpxchgl %1,%2"
|
||||
: "=a" (prev)
|
||||
: "q" (new_value), "m" (*ptr), "0" (old_value)
|
||||
: "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
__asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg.
|
||||
: "=r" (new_value)
|
||||
: "m" (*ptr), "0" (new_value)
|
||||
: "memory");
|
||||
return new_value; // Now it's the previous value.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
Atomic32 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddl %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now holds the old value of *ptr
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
Atomic32 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddl %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now holds the old value of *ptr
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
__asm__ __volatile__("mfence" : : : "memory");
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
*ptr = value; // An x86 store acts as a release barrier.
|
||||
// See comments in Atomic64 version of Release_Store(), below.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
|
||||
// See comments in Atomic64 version of Release_Store(), below.
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev;
|
||||
__asm__ __volatile__("lock; cmpxchgq %1,%2"
|
||||
: "=a" (prev)
|
||||
: "q" (new_value), "m" (*ptr), "0" (old_value)
|
||||
: "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
__asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg.
|
||||
: "=r" (new_value)
|
||||
: "m" (*ptr), "0" (new_value)
|
||||
: "memory");
|
||||
return new_value; // Now it's the previous value.
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
Atomic64 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddq %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now contains the previous value of *ptr
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
Atomic64 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddq %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now contains the previous value of *ptr
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
|
||||
*ptr = value; // An x86 store acts as a release barrier
|
||||
// for current AMD/Intel chips as of Jan 2008.
|
||||
// See also Acquire_Load(), below.
|
||||
|
||||
// When new chips come out, check:
|
||||
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
|
||||
// System Programming Guide, Chatper 7: Multiple-processor management,
|
||||
// Section 7.2, Memory Ordering.
|
||||
// Last seen at:
|
||||
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
|
||||
//
|
||||
// x86 stores/loads fail to act as barriers for a few instructions (clflush
|
||||
// maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
|
||||
// not generated by the compiler, and are rare. Users of these instructions
|
||||
// need to know about cache behaviour in any case since all of these involve
|
||||
// either flushing cache lines or non-temporal cache hints.
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
|
||||
// for current AMD/Intel chips as of Jan 2008.
|
||||
// See also Release_Store(), above.
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
#endif // defined(__x86_64__)
|
||||
|
||||
} // namespace base::subtle
|
||||
} // namespace base
|
||||
|
||||
#undef ATOMICOPS_COMPILER_BARRIER
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
|
224
include/base/internal/cef_atomicops_x86_msvc.h
Normal file
224
include/base/internal/cef_atomicops_x86_msvc.h
Normal file
@ -0,0 +1,224 @@
|
||||
// Copyright (c) 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_atomicops.h
|
||||
// instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
// windows.h #defines this (only on x64). This causes problems because the
|
||||
// public API also uses MemoryBarrier at the public name for this fence. So, on
|
||||
// X64, undef it, and call its documented
|
||||
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
|
||||
// implementation directly.
|
||||
#undef MemoryBarrier
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
LONG result = _InterlockedCompareExchange(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(new_value),
|
||||
static_cast<LONG>(old_value));
|
||||
return static_cast<Atomic32>(result);
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
LONG result = _InterlockedExchange(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(new_value));
|
||||
return static_cast<Atomic32>(result);
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return _InterlockedExchangeAdd(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(increment)) + increment;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
#error "We require at least vs2005 for MemoryBarrier"
|
||||
#endif
|
||||
inline void MemoryBarrier() {
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
// See #undef and note at the top of this file.
|
||||
__faststorefence();
|
||||
#else
|
||||
// We use MemoryBarrier from WinNT.h
|
||||
::MemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
// See comments in Atomic64 version of Release_Store() below.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
PVOID result = InterlockedCompareExchangePointer(
|
||||
reinterpret_cast<volatile PVOID*>(ptr),
|
||||
reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
|
||||
return reinterpret_cast<Atomic64>(result);
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
PVOID result = InterlockedExchangePointer(
|
||||
reinterpret_cast<volatile PVOID*>(ptr),
|
||||
reinterpret_cast<PVOID>(new_value));
|
||||
return reinterpret_cast<Atomic64>(result);
|
||||
}
|
||||
|
||||
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return InterlockedExchangeAdd64(
|
||||
reinterpret_cast<volatile LONGLONG*>(ptr),
|
||||
static_cast<LONGLONG>(increment)) + increment;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
|
||||
// When new chips come out, check:
|
||||
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
|
||||
// System Programming Guide, Chatper 7: Multiple-processor management,
|
||||
// Section 7.2, Memory Ordering.
|
||||
// Last seen at:
|
||||
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
} // namespace base::subtle
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
|
2811
include/base/internal/cef_bind_internal.h
Normal file
2811
include/base/internal/cef_bind_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
390
include/base/internal/cef_bind_internal_win.h
Normal file
390
include/base/internal/cef_bind_internal_win.h
Normal file
@ -0,0 +1,390 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_bind.h instead.
|
||||
|
||||
// Specializations of RunnableAdapter<> for Windows specific calling
|
||||
// conventions. Please see base/bind_internal.h for more info.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
|
||||
|
||||
// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all
|
||||
// the same as __cdecl which would turn the following specializations into
|
||||
// multiple definitions.
|
||||
#if !defined(ARCH_CPU_X86_64)
|
||||
|
||||
namespace base {
|
||||
namespace cef_internal {
|
||||
|
||||
template <typename Functor>
|
||||
class RunnableAdapter;
|
||||
|
||||
// __stdcall Function: Arity 0.
|
||||
template <typename R>
|
||||
class RunnableAdapter<R(__stdcall *)()> {
|
||||
public:
|
||||
typedef R (RunType)();
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)())
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run() {
|
||||
return function_();
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)();
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 0.
|
||||
template <typename R>
|
||||
class RunnableAdapter<R(__fastcall *)()> {
|
||||
public:
|
||||
typedef R (RunType)();
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)())
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run() {
|
||||
return function_();
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)();
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 1.
|
||||
template <typename R, typename A1>
|
||||
class RunnableAdapter<R(__stdcall *)(A1)> {
|
||||
public:
|
||||
typedef R (RunType)(A1);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
|
||||
return function_(a1);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 1.
|
||||
template <typename R, typename A1>
|
||||
class RunnableAdapter<R(__fastcall *)(A1)> {
|
||||
public:
|
||||
typedef R (RunType)(A1);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
|
||||
return function_(a1);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 2.
|
||||
template <typename R, typename A1, typename A2>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2) {
|
||||
return function_(a1, a2);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 2.
|
||||
template <typename R, typename A1, typename A2>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2) {
|
||||
return function_(a1, a2);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 3.
|
||||
template <typename R, typename A1, typename A2, typename A3>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2, A3)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3) {
|
||||
return function_(a1, a2, a3);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2, A3);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 3.
|
||||
template <typename R, typename A1, typename A2, typename A3>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2, A3)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3) {
|
||||
return function_(a1, a2, a3);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2, A3);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 4.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4) {
|
||||
return function_(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2, A3, A4);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 4.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4) {
|
||||
return function_(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2, A3, A4);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 5.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5) {
|
||||
return function_(a1, a2, a3, a4, a5);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2, A3, A4, A5);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 5.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5) {
|
||||
return function_(a1, a2, a3, a4, a5);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2, A3, A4, A5);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 6.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5, A6);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename CallbackParamTraits<A6>::ForwardType a6) {
|
||||
return function_(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2, A3, A4, A5, A6);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 6.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5, A6);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename CallbackParamTraits<A6>::ForwardType a6) {
|
||||
return function_(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2, A3, A4, A5, A6);
|
||||
};
|
||||
|
||||
// __stdcall Function: Arity 7.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6, typename A7>
|
||||
class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6, A7)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);
|
||||
|
||||
explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6, A7))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename CallbackParamTraits<A6>::ForwardType a6,
|
||||
typename CallbackParamTraits<A7>::ForwardType a7) {
|
||||
return function_(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__stdcall *function_)(A1, A2, A3, A4, A5, A6, A7);
|
||||
};
|
||||
|
||||
// __fastcall Function: Arity 7.
|
||||
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||
typename A5, typename A6, typename A7>
|
||||
class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6, A7)> {
|
||||
public:
|
||||
typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);
|
||||
|
||||
explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6, A7))
|
||||
: function_(function) {
|
||||
}
|
||||
|
||||
R Run(typename CallbackParamTraits<A1>::ForwardType a1,
|
||||
typename CallbackParamTraits<A2>::ForwardType a2,
|
||||
typename CallbackParamTraits<A3>::ForwardType a3,
|
||||
typename CallbackParamTraits<A4>::ForwardType a4,
|
||||
typename CallbackParamTraits<A5>::ForwardType a5,
|
||||
typename CallbackParamTraits<A6>::ForwardType a6,
|
||||
typename CallbackParamTraits<A7>::ForwardType a7) {
|
||||
return function_(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
|
||||
private:
|
||||
R (__fastcall *function_)(A1, A2, A3, A4, A5, A6, A7);
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
} // namespace base
|
||||
|
||||
#endif // !defined(ARCH_CPU_X86_64)
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
|
205
include/base/internal/cef_callback_internal.h
Normal file
205
include/base/internal/cef_callback_internal.h
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2012 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_bind.h or
|
||||
// base/cef_callback.h instead.
|
||||
|
||||
// This file contains utility functions and classes that help the
|
||||
// implementation, and management of the Callback objects.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
|
||||
template <typename T>
|
||||
class ScopedVector;
|
||||
|
||||
namespace base {
|
||||
namespace cef_internal {
|
||||
|
||||
// BindStateBase is used to provide an opaque handle that the Callback
|
||||
// class can use to represent a function object with bound arguments. It
|
||||
// behaves as an existential type that is used by a corresponding
|
||||
// DoInvoke function to perform the function execution. This allows
|
||||
// us to shield the Callback class from the types of the bound argument via
|
||||
// "type erasure."
|
||||
class BindStateBase : public RefCountedThreadSafe<BindStateBase> {
|
||||
protected:
|
||||
friend class RefCountedThreadSafe<BindStateBase>;
|
||||
virtual ~BindStateBase() {}
|
||||
};
|
||||
|
||||
// Holds the Callback methods that don't require specialization to reduce
|
||||
// template bloat.
|
||||
class CallbackBase {
|
||||
public:
|
||||
// Returns true if Callback is null (doesn't refer to anything).
|
||||
bool is_null() const { return bind_state_.get() == NULL; }
|
||||
|
||||
// Returns the Callback into an uninitialized state.
|
||||
void Reset();
|
||||
|
||||
protected:
|
||||
// In C++, it is safe to cast function pointers to function pointers of
|
||||
// another type. It is not okay to use void*. We create a InvokeFuncStorage
|
||||
// that that can store our function pointer, and then cast it back to
|
||||
// the original type on usage.
|
||||
typedef void(*InvokeFuncStorage)(void);
|
||||
|
||||
// Returns true if this callback equals |other|. |other| may be null.
|
||||
bool Equals(const CallbackBase& other) const;
|
||||
|
||||
// Allow initializing of |bind_state_| via the constructor to avoid default
|
||||
// initialization of the scoped_refptr. We do not also initialize
|
||||
// |polymorphic_invoke_| here because doing a normal assignment in the
|
||||
// derived Callback templates makes for much nicer compiler errors.
|
||||
explicit CallbackBase(BindStateBase* bind_state);
|
||||
|
||||
// Force the destructor to be instantiated inside this translation unit so
|
||||
// that our subclasses will not get inlined versions. Avoids more template
|
||||
// bloat.
|
||||
~CallbackBase();
|
||||
|
||||
scoped_refptr<BindStateBase> bind_state_;
|
||||
InvokeFuncStorage polymorphic_invoke_;
|
||||
};
|
||||
|
||||
// A helper template to determine if given type is non-const move-only-type,
|
||||
// i.e. if a value of the given type should be passed via .Pass() in a
|
||||
// destructive way.
|
||||
template <typename T> struct IsMoveOnlyType {
|
||||
template <typename U>
|
||||
static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
|
||||
|
||||
template <typename U>
|
||||
static NoType Test(...);
|
||||
|
||||
static const bool value = sizeof(Test<T>(0)) == sizeof(YesType) &&
|
||||
!is_const<T>::value;
|
||||
};
|
||||
|
||||
// This is a typetraits object that's used to take an argument type, and
|
||||
// extract a suitable type for storing and forwarding arguments.
|
||||
//
|
||||
// In particular, it strips off references, and converts arrays to
|
||||
// pointers for storage; and it avoids accidentally trying to create a
|
||||
// "reference of a reference" if the argument is a reference type.
|
||||
//
|
||||
// This array type becomes an issue for storage because we are passing bound
|
||||
// parameters by const reference. In this case, we end up passing an actual
|
||||
// array type in the initializer list which C++ does not allow. This will
|
||||
// break passing of C-string literals.
|
||||
template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
|
||||
struct CallbackParamTraits {
|
||||
typedef const T& ForwardType;
|
||||
typedef T StorageType;
|
||||
};
|
||||
|
||||
// The Storage should almost be impossible to trigger unless someone manually
|
||||
// specifies type of the bind parameters. However, in case they do,
|
||||
// this will guard against us accidentally storing a reference parameter.
|
||||
//
|
||||
// The ForwardType should only be used for unbound arguments.
|
||||
template <typename T>
|
||||
struct CallbackParamTraits<T&, false> {
|
||||
typedef T& ForwardType;
|
||||
typedef T StorageType;
|
||||
};
|
||||
|
||||
// Note that for array types, we implicitly add a const in the conversion. This
|
||||
// means that it is not possible to bind array arguments to functions that take
|
||||
// a non-const pointer. Trying to specialize the template based on a "const
|
||||
// T[n]" does not seem to match correctly, so we are stuck with this
|
||||
// restriction.
|
||||
template <typename T, size_t n>
|
||||
struct CallbackParamTraits<T[n], false> {
|
||||
typedef const T* ForwardType;
|
||||
typedef const T* StorageType;
|
||||
};
|
||||
|
||||
// See comment for CallbackParamTraits<T[n]>.
|
||||
template <typename T>
|
||||
struct CallbackParamTraits<T[], false> {
|
||||
typedef const T* ForwardType;
|
||||
typedef const T* StorageType;
|
||||
};
|
||||
|
||||
// Parameter traits for movable-but-not-copyable scopers.
|
||||
//
|
||||
// Callback<>/Bind() understands movable-but-not-copyable semantics where
|
||||
// the type cannot be copied but can still have its state destructively
|
||||
// transferred (aka. moved) to another instance of the same type by calling a
|
||||
// helper function. When used with Bind(), this signifies transferal of the
|
||||
// object's state to the target function.
|
||||
//
|
||||
// For these types, the ForwardType must not be a const reference, or a
|
||||
// reference. A const reference is inappropriate, and would break const
|
||||
// correctness, because we are implementing a destructive move. A non-const
|
||||
// reference cannot be used with temporaries which means the result of a
|
||||
// function or a cast would not be usable with Callback<> or Bind().
|
||||
template <typename T>
|
||||
struct CallbackParamTraits<T, true> {
|
||||
typedef T ForwardType;
|
||||
typedef T StorageType;
|
||||
};
|
||||
|
||||
// CallbackForward() is a very limited simulation of C++11's std::forward()
|
||||
// used by the Callback/Bind system for a set of movable-but-not-copyable
|
||||
// types. It is needed because forwarding a movable-but-not-copyable
|
||||
// argument to another function requires us to invoke the proper move
|
||||
// operator to create a rvalue version of the type. The supported types are
|
||||
// whitelisted below as overloads of the CallbackForward() function. The
|
||||
// default template compiles out to be a no-op.
|
||||
//
|
||||
// In C++11, std::forward would replace all uses of this function. However, it
|
||||
// is impossible to implement a general std::forward with C++11 due to a lack
|
||||
// of rvalue references.
|
||||
//
|
||||
// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
|
||||
// simulate std::forward() and forward the result of one Callback as a
|
||||
// parameter to another callback. This is to support Callbacks that return
|
||||
// the movable-but-not-copyable types whitelisted above.
|
||||
template <typename T>
|
||||
typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) {
|
||||
return t.Pass();
|
||||
}
|
||||
|
||||
} // namespace cef_internal
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
|
87
include/base/internal/cef_lock_impl.h
Normal file
87
include/base/internal/cef_lock_impl.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_lock.h instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
namespace base {
|
||||
namespace cef_internal {
|
||||
|
||||
// This class implements the underlying platform-specific spin-lock mechanism
|
||||
// used for the Lock class. Most users should not use LockImpl directly, but
|
||||
// should instead use Lock.
|
||||
class LockImpl {
|
||||
public:
|
||||
#if defined(OS_WIN)
|
||||
typedef CRITICAL_SECTION NativeHandle;
|
||||
#elif defined(OS_POSIX)
|
||||
typedef pthread_mutex_t NativeHandle;
|
||||
#endif
|
||||
|
||||
LockImpl();
|
||||
~LockImpl();
|
||||
|
||||
// If the lock is not held, take it and return true. If the lock is already
|
||||
// held by something else, immediately return false.
|
||||
bool Try();
|
||||
|
||||
// Take the lock, blocking until it is available if necessary.
|
||||
void Lock();
|
||||
|
||||
// Release the lock. This must only be called by the lock's holder: after
|
||||
// a successful call to Try, or a call to Lock.
|
||||
void Unlock();
|
||||
|
||||
// Return the native underlying lock.
|
||||
// TODO(awalker): refactor lock and condition variables so that this is
|
||||
// unnecessary.
|
||||
NativeHandle* native_handle() { return &native_handle_; }
|
||||
|
||||
private:
|
||||
NativeHandle native_handle_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LockImpl);
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_
|
154
include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h
Normal file
154
include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h
Normal file
@ -0,0 +1,154 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_callback.h instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/base/cef_template_util.h"
|
||||
#include "include/base/cef_tuple.h"
|
||||
|
||||
// It is dangerous to post a task with a T* argument where T is a subtype of
|
||||
// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the
|
||||
// object may already have been deleted since it was not held with a
|
||||
// scoped_refptr. Example: http://crbug.com/27191
|
||||
// The following set of traits are designed to generate a compile error
|
||||
// whenever this antipattern is attempted.
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace cef_internal {
|
||||
|
||||
template <typename T>
|
||||
struct NeedsScopedRefptrButGetsRawPtr {
|
||||
#if defined(OS_WIN)
|
||||
enum {
|
||||
value = base::false_type::value
|
||||
};
|
||||
#else
|
||||
enum {
|
||||
// Human readable translation: you needed to be a scoped_refptr if you are a
|
||||
// raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase)
|
||||
// type.
|
||||
value = (is_pointer<T>::value &&
|
||||
(is_convertible<T, subtle::RefCountedBase*>::value ||
|
||||
is_convertible<T, subtle::RefCountedThreadSafeBase*>::value))
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Params>
|
||||
struct ParamsUseScopedRefptrCorrectly {
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple0> {
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > {
|
||||
enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value };
|
||||
};
|
||||
|
||||
template <typename A, typename B>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<D>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<E>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E,
|
||||
typename F>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<F>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E,
|
||||
typename F, typename G>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<F>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<G>::value) };
|
||||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E,
|
||||
typename F, typename G, typename H>
|
||||
struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > {
|
||||
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<F>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<G>::value ||
|
||||
NeedsScopedRefptrButGetsRawPtr<H>::value) };
|
||||
};
|
||||
|
||||
} // namespace cef_internal
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
|
70
include/base/internal/cef_thread_checker_impl.h
Normal file
70
include/base/internal/cef_thread_checker_impl.h
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Do not include this header file directly. Use base/cef_thread_checker.h
|
||||
// instead.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_
|
||||
#define CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_
|
||||
|
||||
#include "include/base/cef_lock.h"
|
||||
#include "include/base/cef_platform_thread.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Real implementation of ThreadChecker, for use in debug mode, or
|
||||
// for temporary use in release mode (e.g. to CHECK on a threading issue
|
||||
// seen only in the wild).
|
||||
//
|
||||
// Note: You should almost always use the ThreadChecker class to get the
|
||||
// right version for your build configuration.
|
||||
class ThreadCheckerImpl {
|
||||
public:
|
||||
ThreadCheckerImpl();
|
||||
~ThreadCheckerImpl();
|
||||
|
||||
bool CalledOnValidThread() const;
|
||||
|
||||
// Changes the thread that is checked for in CalledOnValidThread. This may
|
||||
// be useful when an object may be created on one thread and then used
|
||||
// exclusively on another thread.
|
||||
void DetachFromThread();
|
||||
|
||||
private:
|
||||
void EnsureThreadIdAssigned() const;
|
||||
|
||||
mutable base::Lock lock_;
|
||||
// This is mutable so that CalledOnValidThread can set it.
|
||||
// It's guarded by |lock_|.
|
||||
mutable PlatformThreadRef valid_thread_id_;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_
|
Reference in New Issue
Block a user