Introduce the use of Chromium types (issue #1336).

Changes to the CEF public API:
- Add base::Bind, base::Callback, base::Lock, base::WeakPtr, scoped_refptr, scoped_ptr and supporting types.
- Add include/wrapper/cef_closure_task.h helpers for converting a base::Closure to a CefTask.
- Change CefRefPtr to extend scoped_refptr.
-- Change CefBase method signatures to match RefCountedThreadSafeBase.
- Change IMPLEMENT_REFCOUNTING to use base::AtomicRefCount*.
-- Remove the CefAtomic* functions.
-- IMPLEMENT_REFCOUNTING now enforces via a compile-time error that the correct class name was passed to the macro.
- Change IMPLEMENT_LOCKING to use base::Lock.
-- Remove the CefCriticalSection class.
-- Deprecate the IMPLEMENT_LOCKING macro.
-- base::Lock will DCHECK() in Debug builds if lock usage is reentrant.
- Move include/internal/cef_tuple.h to include/base/cef_tuple.h.
- Allow an empty |callback| parameter passed to CefBeginTracing.

Changes to the CEF implementation:
- Fix incorrect names passed to the IMPLEMENT_REFCOUNTING macro.
- Fix instances of reentrant locking in the CefXmlObject and CefRequest implementations.
- Remove use of the IMPLEMENT_LOCKING macro.

Changes to cef_unittests:
- Add tests/unittests/chromium_includes.h and always include it first from unit test .cc files to avoid name conflicts with Chromium types.
- Fix wrong header include ordering.
- Remove use of the IMPLEMENT_LOCKING macro.

Changes to cefclient and cefsimple:
- Use base::Bind and cef_closure_task.h instead of NewCefRunnable*.
- Remove use of the IMPEMENT_LOCKING macro.
- Fix incorrect/unnecessary locking.
- Add additional runtime thread checks.
- Windows: Perform actions on the UI thread instead of the main thread when running in multi-threaded-message-loop mode to avoid excessive locking.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1769 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-07-14 22:18:51 +00:00
parent c260a2d166
commit 122397acfc
314 changed files with 13077 additions and 1242 deletions

View File

@ -9,10 +9,35 @@
],
'variables': {
'includes_common': [
'include/base/cef_atomic_ref_count.h',
'include/base/cef_atomicops.h',
'include/base/cef_basictypes.h',
'include/base/cef_bind.h',
'include/base/cef_bind_helpers.h',
'include/base/cef_build.h',
'include/base/cef_callback.h',
'include/base/cef_callback_forward.h',
'include/base/cef_callback_helpers.h',
'include/base/cef_callback_list.h',
'include/base/cef_cancelable_callback.h',
'include/base/cef_lock.h',
'include/base/cef_logging.h',
'include/base/cef_macros.h',
'include/base/cef_move.h',
'include/base/cef_platform_thread.h',
'include/base/cef_ref_counted.h',
'include/base/cef_scoped_ptr.h',
'include/base/cef_template_util.h',
'include/base/cef_thread_checker.h',
'include/base/cef_thread_collision_warner.h',
'include/base/cef_trace_event.h',
'include/base/cef_tuple.h',
'include/base/cef_weak_ptr.h',
'include/base/internal/cef_bind_internal.h',
'include/base/internal/cef_callback_internal.h',
'include/base/internal/cef_lock_impl.h',
'include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h',
'include/base/internal/cef_thread_checker_impl.h',
'include/cef_base.h',
'include/cef_pack_resources.h',
'include/cef_pack_strings.h',
@ -27,9 +52,9 @@
'include/internal/cef_string_multimap.h',
'include/internal/cef_string_types.h',
'include/internal/cef_string_wrappers.h',
'include/internal/cef_thread_internal.h',
'include/internal/cef_time.h',
'include/internal/cef_trace_event_internal.h',
'include/internal/cef_tuple.h',
'include/internal/cef_types.h',
'include/internal/cef_types_wrappers.h',
'<@(autogen_cpp_includes)',
@ -40,22 +65,30 @@
],
'includes_wrapper': [
'include/wrapper/cef_byte_read_handler.h',
'include/wrapper/cef_closure_task.h',
'include/wrapper/cef_helpers.h',
'include/wrapper/cef_message_router.h',
'include/wrapper/cef_stream_resource_handler.h',
'include/wrapper/cef_xml_object.h',
'include/wrapper/cef_zip_archive.h',
],
'includes_win': [
'include/base/internal/cef_atomicops_x86_msvc.h',
'include/base/internal/cef_bind_internal_win.h',
'include/cef_sandbox_win.h',
'include/internal/cef_types_win.h',
'include/internal/cef_win.h',
],
'includes_mac': [
'include/base/internal/cef_atomicops_atomicword_compat.h',
'include/base/internal/cef_atomicops_mac.h',
'include/cef_application_mac.h',
'include/internal/cef_mac.h',
'include/internal/cef_types_mac.h',
],
'includes_linux': [
'include/base/internal/cef_atomicops_atomicword_compat.h',
'include/base/internal/cef_atomicops_x86_gcc.h',
'include/internal/cef_linux.h',
'include/internal/cef_types_linux.h',
],
@ -70,7 +103,17 @@
'<@(autogen_library_side)',
],
'libcef_dll_wrapper_sources_common': [
'libcef_dll/base/cef_atomicops_x86_gcc.cc',
'libcef_dll/base/cef_bind_helpers.cc',
'libcef_dll/base/cef_callback_helpers.cc',
'libcef_dll/base/cef_callback_internal.cc',
'libcef_dll/base/cef_lock.cc',
'libcef_dll/base/cef_lock_impl.cc',
'libcef_dll/base/cef_logging.cc',
'libcef_dll/base/cef_ref_counted.cc',
'libcef_dll/base/cef_thread_checker_impl.cc',
'libcef_dll/base/cef_thread_collision_warner.cc',
'libcef_dll/base/cef_weak_ptr.cc',
'libcef_dll/cpptoc/base_cpptoc.h',
'libcef_dll/cpptoc/cpptoc.h',
'libcef_dll/ctocpp/base_ctocpp.h',
@ -79,6 +122,7 @@
'libcef_dll/transfer_util.h',
'libcef_dll/wrapper/cef_browser_info_map.h',
'libcef_dll/wrapper/cef_byte_read_handler.cc',
'libcef_dll/wrapper/cef_closure_task.cc',
'libcef_dll/wrapper/cef_message_router.cc',
'libcef_dll/wrapper/cef_stream_resource_handler.cc',
'libcef_dll/wrapper/cef_xml_object.cc',

View 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_

View 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_

View 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
View 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 internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void()>
::UnboundRunType>
Bind(Functor functor) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
typedef internal::BindState<RunnableType, RunType, void()> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)));
}
template <typename Functor, typename P1>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1));
}
template <typename Functor, typename P1, typename P2>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2));
}
template <typename Functor, typename P1, typename P2, typename P3>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(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 internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(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 internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename 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 internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename 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 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(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
p7_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6,
p7));
}
} // namespace base
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_BASE_CEF_BIND_H_

View 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 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 internal
template <typename T>
static inline internal::UnretainedWrapper<T> Unretained(T* o) {
return internal::UnretainedWrapper<T>(o);
}
template <typename T>
static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
return internal::ConstRefWrapper<T>(o);
}
template <typename T>
static inline internal::OwnedWrapper<T> Owned(T* o) {
return 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 internal::PassedWrapper<T> Passed(T scoper) {
return internal::PassedWrapper<T>(scoper.Pass());
}
template <typename T>
static inline internal::PassedWrapper<T> Passed(T* scoper) {
return internal::PassedWrapper<T>(scoper->Pass());
}
template <typename T>
static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
return internal::IgnoreResultHelper<T>(data);
}
template <typename T>
static inline internal::IgnoreResultHelper<Callback<T> >
IgnoreResult(const Callback<T>& data) {
return 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_

View File

@ -77,6 +77,42 @@
#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 build/build_config.h
#endif
// Annotate a virtual method indicating it must be overriding a virtual
// method in the parent class.
// Use like:
@ -91,6 +127,27 @@
#define OVERRIDE
#endif
// 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>.
#if defined(COMPILER_GCC)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
#endif
// 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 = ...;
#if defined(COMPILER_GCC)
#define ALLOW_UNUSED __attribute__((unused))
#else
#define ALLOW_UNUSED
#endif
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_BASE_CEF_BUILD_H_

807
include/base/cef_callback.h Normal file
View 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 internal {
template <typename Runnable, typename RunType, typename BoundArgsType>
struct BindState;
} // namespace internal
template <typename R>
class Callback<R(void)> : public 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(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 =
&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)(
internal::BindStateBase*);
};
template <typename R, typename A1>
class Callback<R(A1)> : public 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType);
};
template <typename R, typename A1, typename A2>
class Callback<R(A1, A2)> : public 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3>
class Callback<R(A1, A2, A3)> : public 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A1, A2, A3, A4)> : public 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename 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 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename 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 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename 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 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(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 =
&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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6,
typename internal::CallbackParamTraits<A7>::ForwardType a7) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6),
internal::CallbackForward(a7));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename internal::CallbackParamTraits<A6>::ForwardType,
typename 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_

View 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_

View 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_

View 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 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 internal
template <typename Sig> class CallbackList;
template <>
class CallbackList<void(void)>
: public internal::CallbackListBase<Callback<void(void)> > {
public:
typedef Callback<void(void)> CallbackType;
CallbackList() {}
void Notify() {
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 internal::CallbackListBase<Callback<void(A1)> > {
public:
typedef Callback<void(A1)> CallbackType;
CallbackList() {}
void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1) {
typename 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 internal::CallbackListBase<Callback<void(A1, A2)> > {
public:
typedef Callback<void(A1, A2)> CallbackType;
CallbackList() {}
void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2) {
typename 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 internal::CallbackListBase<Callback<void(A1, A2, A3)> > {
public:
typedef Callback<void(A1, A2, A3)> CallbackType;
CallbackList() {}
void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3) {
typename 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 internal::CallbackListBase<Callback<void(A1, A2, A3, A4)> > {
public:
typedef Callback<void(A1, A2, A3, A4)> CallbackType;
CallbackList() {}
void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4) {
typename 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 internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5)> > {
public:
typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
CallbackList() {}
void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5) {
typename 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 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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6) {
typename 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 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 internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6,
typename internal::CallbackParamTraits<A7>::ForwardType a7) {
typename 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_

View 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
View 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.
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_

View File

@ -158,7 +158,8 @@
#include "include/base/cef_macros.h"
#include "include/internal/cef_logging_internal.h"
namespace cef_logging {
namespace cef {
namespace logging {
// Gets the current log level.
inline int GetMinLogLevel() {
@ -193,19 +194,19 @@ const LogSeverity LOG_DFATAL = LOG_FATAL;
// 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 , \
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 , \
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 , \
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 , \
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 , \
cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_DFATAL , \
##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_INFO \
@ -237,19 +238,19 @@ const LogSeverity LOG_0 = LOG_ERROR;
// 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())
((::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__))
((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)
!(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
@ -270,7 +271,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
// The VLOG macros log with negative verbosities.
#define VLOG_STREAM(verbose_level) \
cef_logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
cef::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
#define VLOG(verbose_level) \
LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
@ -281,12 +282,12 @@ const LogSeverity LOG_0 = LOG_ERROR;
#if defined (OS_WIN)
#define VPLOG_STREAM(verbose_level) \
cef_logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \
::cef_logging::GetLastSystemErrorCode()).stream()
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()
cef::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
::cef::logging::GetLastSystemErrorCode()).stream()
#endif
#define VPLOG(verbose_level) \
@ -306,11 +307,11 @@ const LogSeverity LOG_0 = LOG_ERROR;
#if defined(OS_WIN)
#define PLOG_STREAM(severity) \
COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
::cef_logging::GetLastSystemErrorCode()).stream()
::cef::logging::GetLastSystemErrorCode()).stream()
#elif defined(OS_POSIX)
#define PLOG_STREAM(severity) \
COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \
::cef_logging::GetLastSystemErrorCode()).stream()
::cef::logging::GetLastSystemErrorCode()).stream()
#endif
#define PLOG(severity) \
@ -321,7 +322,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
// The actual stream used isn't important.
#define EAT_STREAM_PARAMETERS \
true ? (void) 0 : ::cef_logging::LogMessageVoidify() & LOG_STREAM(FATAL)
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
@ -345,9 +346,9 @@ const LogSeverity LOG_0 = LOG_ERROR;
// CHECK_EQ(...) else { ... } work properly.
#define CHECK_OP(name, op, val1, val2) \
if (std::string* _result = \
cef_logging::Check##name##Impl((val1), (val2), \
cef::logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
cef_logging::LogMessage(__FILE__, __LINE__, _result).stream()
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
@ -509,10 +510,10 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
#define DCHECK_OP(name, op, val1, val2) \
if (DCHECK_IS_ON) \
if (std::string* _result = \
cef_logging::Check##name##Impl((val1), (val2), \
cef::logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
cef_logging::LogMessage( \
__FILE__, __LINE__, ::cef_logging::LOG_DCHECK, \
cef::logging::LogMessage( \
__FILE__, __LINE__, ::cef::logging::LOG_DCHECK, \
_result).stream()
// Equality/Inequality checks - compare two values, and log a
@ -678,7 +679,8 @@ class ErrnoLogMessage {
};
#endif // OS_WIN
} // namespace cef_logging
} // 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

View File

@ -118,6 +118,100 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
#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
// 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
View 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_

View 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_

View 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_

View File

@ -0,0 +1,623 @@
// 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_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 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 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::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::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::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::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::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_

View 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 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 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(internal::ConvertHelper::Test<To>(
internal::ConvertHelper::Create<From>())) ==
sizeof(internal::YesType)> {
};
template <typename T>
struct is_class
: integral_constant<bool,
sizeof(internal::IsClassHelper::Test<T>(0)) ==
sizeof(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_

View 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_

View 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_

View File

@ -1,4 +1,5 @@
// Copyright (c) 2006-2011 Google Inc. All rights reserved.
// 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
@ -26,8 +27,6 @@
// 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 identical to base/tuple.h
// A Tuple is a generic templatized container, similar in concept to std::pair.
// There are classes Tuple0 to Tuple6, cooresponding to the number of elements
@ -53,18 +52,25 @@
// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
// // foo->SomeMeth(1, 2, 3);
#ifndef CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_
#define CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_
#ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_
#define CEF_INCLUDE_BASE_CEF_TUPLE_H_
#pragma once
// If base/tuple.h is included first then exclude this file. This is to
// facilitate the use of both base/bind.h and cef_runnable.h in unit tests.
#ifndef BASE_TUPLE_H__
#if defined(BASE_TUPLE_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/tuple.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_helpers.h"
#if defined(OS_CHROMEOS)
// To troubleshoot crosbug.com/7327.
#include "base/logging.h"
#endif
// Traits ----------------------------------------------------------------------
//
// A simple traits class for tuple arguments.
@ -148,7 +154,7 @@ struct Tuple3 {
Tuple3(typename TupleTraits<A>::ParamType a,
typename TupleTraits<B>::ParamType b,
typename TupleTraits<C>::ParamType c)
: a(a), b(b), c(c) {
: a(a), b(b), c(c){
}
A a;
@ -574,57 +580,86 @@ inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) {
template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
(obj->*method)(arg);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg));
}
template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
#if defined(OS_CHROMEOS)
// To troubleshoot crosbug.com/7327.
CHECK(obj);
CHECK(&arg);
CHECK(method);
#endif
(obj->*method)(arg.a);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a));
}
template<class ObjT, class Method, class A, class B>
inline void DispatchToMethod(ObjT* obj,
Method method,
const Tuple2<A, B>& arg) {
(obj->*method)(arg.a, arg.b);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b));
}
template<class ObjT, class Method, class A, class B, class C>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<A, B, C>& arg) {
(obj->*method)(arg.a, arg.b, arg.c);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c));
}
template<class ObjT, class Method, class A, class B, class C, class D>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<A, B, C, D>& arg) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<A, B, C, D, E>& arg) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E,
class F>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<A, B, C, D, E, F>& arg) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E,
class F, class G>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple7<A, B, C, D, E, F, G>& arg) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f),
base::internal::UnwrapTraits<G>::Unwrap(arg.g));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E,
class F, class G, class H>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple8<A, B, C, D, E, F, G, H>& arg) {
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f),
base::internal::UnwrapTraits<G>::Unwrap(arg.g),
base::internal::UnwrapTraits<H>::Unwrap(arg.h));
}
// Static Dispatchers with no out params.
@ -641,49 +676,77 @@ inline void DispatchToFunction(Function function, const A& arg) {
template <class Function, class A>
inline void DispatchToFunction(Function function, const Tuple1<A>& arg) {
(*function)(arg.a);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a));
}
template<class Function, class A, class B>
inline void DispatchToFunction(Function function, const Tuple2<A, B>& arg) {
(*function)(arg.a, arg.b);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b));
}
template<class Function, class A, class B, class C>
inline void DispatchToFunction(Function function, const Tuple3<A, B, C>& arg) {
(*function)(arg.a, arg.b, arg.c);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c));
}
template<class Function, class A, class B, class C, class D>
inline void DispatchToFunction(Function function,
const Tuple4<A, B, C, D>& arg) {
(*function)(arg.a, arg.b, arg.c, arg.d);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d));
}
template<class Function, class A, class B, class C, class D, class E>
inline void DispatchToFunction(Function function,
const Tuple5<A, B, C, D, E>& arg) {
(*function)(arg.a, arg.b, arg.c, arg.d, arg.e);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e));
}
template<class Function, class A, class B, class C, class D, class E, class F>
inline void DispatchToFunction(Function function,
const Tuple6<A, B, C, D, E, F>& arg) {
(*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f));
}
template<class Function, class A, class B, class C, class D, class E, class F,
class G>
inline void DispatchToFunction(Function function,
const Tuple7<A, B, C, D, E, F, G>& arg) {
(*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f),
base::internal::UnwrapTraits<G>::Unwrap(arg.g));
}
template<class Function, class A, class B, class C, class D, class E, class F,
class G, class H>
inline void DispatchToFunction(Function function,
const Tuple8<A, B, C, D, E, F, G, H>& arg) {
(*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h);
(*function)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f),
base::internal::UnwrapTraits<G>::Unwrap(arg.g),
base::internal::UnwrapTraits<H>::Unwrap(arg.h));
}
// Dispatchers with 0 out param (as a Tuple0).
@ -697,46 +760,61 @@ inline void DispatchToMethod(ObjT* obj,
template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) {
(obj->*method)(arg);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg));
}
template <class ObjT, class Method, class A>
inline void DispatchToMethod(ObjT* obj,
Method method,
const Tuple1<A>& arg, Tuple0*) {
(obj->*method)(arg.a);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a));
}
template<class ObjT, class Method, class A, class B>
inline void DispatchToMethod(ObjT* obj,
Method method,
const Tuple2<A, B>& arg, Tuple0*) {
(obj->*method)(arg.a, arg.b);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b));
}
template<class ObjT, class Method, class A, class B, class C>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<A, B, C>& arg, Tuple0*) {
(obj->*method)(arg.a, arg.b, arg.c);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c));
}
template<class ObjT, class Method, class A, class B, class C, class D>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<A, B, C, D>& arg, Tuple0*) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<A, B, C, D, E>& arg, Tuple0*) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e));
}
template<class ObjT, class Method, class A, class B, class C, class D, class E,
class F>
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<A, B, C, D, E, F>& arg, Tuple0*) {
(obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f);
(obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg.a),
base::internal::UnwrapTraits<B>::Unwrap(arg.b),
base::internal::UnwrapTraits<C>::Unwrap(arg.c),
base::internal::UnwrapTraits<D>::Unwrap(arg.d),
base::internal::UnwrapTraits<E>::Unwrap(arg.e),
base::internal::UnwrapTraits<F>::Unwrap(arg.f));
}
// Dispatchers with 1 out param.
@ -762,7 +840,7 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple1<InA>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a);
}
template<class ObjT, class Method, class InA, class InB,
@ -770,7 +848,9 @@ template<class ObjT, class Method, class InA, class InB,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple2<InA, InB>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, in.b, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
&out->a);
}
template<class ObjT, class Method, class InA, class InB, class InC,
@ -778,7 +858,10 @@ template<class ObjT, class Method, class InA, class InB, class InC,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<InA, InB, InC>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, in.b, in.c, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
&out->a);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -786,7 +869,11 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<InA, InB, InC, InD>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
&out->a);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -794,7 +881,12 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<InA, InB, InC, InD, InE>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
&out->a);
}
template<class ObjT, class Method,
@ -803,7 +895,13 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<InA, InB, InC, InD, InE, InF>& in,
Tuple1<OutA>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
base::internal::UnwrapTraits<InF>::Unwrap(in.f),
&out->a);
}
// Dispatchers with 2 out params.
@ -829,7 +927,8 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple1<InA>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, &out->a, &out->b);
(obj->*method)(
base::internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a, &out->b);
}
template<class ObjT, class Method, class InA, class InB,
@ -837,7 +936,10 @@ template<class ObjT, class Method, class InA, class InB,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple2<InA, InB>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, in.b, &out->a, &out->b);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
&out->a,
&out->b);
}
template<class ObjT, class Method, class InA, class InB, class InC,
@ -845,7 +947,11 @@ template<class ObjT, class Method, class InA, class InB, class InC,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<InA, InB, InC>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, in.b, in.c, &out->a, &out->b);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
&out->a,
&out->b);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -853,7 +959,12 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<InA, InB, InC, InD>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
&out->a,
&out->b);
}
template<class ObjT, class Method,
@ -862,7 +973,13 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<InA, InB, InC, InD, InE>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
&out->a,
&out->b);
}
template<class ObjT, class Method,
@ -871,7 +988,14 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<InA, InB, InC, InD, InE, InF>& in,
Tuple2<OutA, OutB>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
base::internal::UnwrapTraits<InF>::Unwrap(in.f),
&out->a,
&out->b);
}
// Dispatchers with 3 out params.
@ -897,7 +1021,10 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple1<InA>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
&out->a,
&out->b,
&out->c);
}
template<class ObjT, class Method, class InA, class InB,
@ -905,7 +1032,11 @@ template<class ObjT, class Method, class InA, class InB,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple2<InA, InB>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, in.b, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
&out->a,
&out->b,
&out->c);
}
template<class ObjT, class Method, class InA, class InB, class InC,
@ -913,7 +1044,12 @@ template<class ObjT, class Method, class InA, class InB, class InC,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<InA, InB, InC>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
&out->a,
&out->b,
&out->c);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -921,7 +1057,13 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<InA, InB, InC, InD>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
&out->a,
&out->b,
&out->c);
}
template<class ObjT, class Method,
@ -930,7 +1072,14 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<InA, InB, InC, InD, InE>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
&out->a,
&out->b,
&out->c);
}
template<class ObjT, class Method,
@ -939,7 +1088,15 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<InA, InB, InC, InD, InE, InF>& in,
Tuple3<OutA, OutB, OutC>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b, &out->c);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
base::internal::UnwrapTraits<InF>::Unwrap(in.f),
&out->a,
&out->b,
&out->c);
}
// Dispatchers with 4 out params.
@ -957,7 +1114,11 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const InA& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in, &out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method, class InA,
@ -965,7 +1126,11 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple1<InA>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method, class InA, class InB,
@ -973,7 +1138,12 @@ template<class ObjT, class Method, class InA, class InB,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple2<InA, InB>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method, class InA, class InB, class InC,
@ -981,7 +1151,13 @@ template<class ObjT, class Method, class InA, class InB, class InC,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<InA, InB, InC>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -989,7 +1165,14 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<InA, InB, InC, InD>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method,
@ -998,8 +1181,15 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<InA, InB, InC, InD, InE>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e,
&out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
&out->a,
&out->b,
&out->c,
&out->d);
}
template<class ObjT, class Method,
@ -1008,8 +1198,16 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<InA, InB, InC, InD, InE, InF>& in,
Tuple4<OutA, OutB, OutC, OutD>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f,
&out->a, &out->b, &out->c, &out->d);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
base::internal::UnwrapTraits<InF>::Unwrap(in.f),
&out->a,
&out->b,
&out->c,
&out->d);
}
// Dispatchers with 5 out params.
@ -1027,7 +1225,12 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const InA& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in, &out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
template<class ObjT, class Method, class InA,
@ -1035,7 +1238,12 @@ template<class ObjT, class Method, class InA,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple1<InA>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
template<class ObjT, class Method, class InA, class InB,
@ -1043,7 +1251,13 @@ template<class ObjT, class Method, class InA, class InB,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple2<InA, InB>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
template<class ObjT, class Method, class InA, class InB, class InC,
@ -1051,7 +1265,14 @@ template<class ObjT, class Method, class InA, class InB, class InC,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple3<InA, InB, InC>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
template<class ObjT, class Method, class InA, class InB, class InC, class InD,
@ -1059,7 +1280,14 @@ template<class ObjT, class Method, class InA, class InB, class InC, class InD,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple4<InA, InB, InC, InD>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d,
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
@ -1069,8 +1297,16 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple5<InA, InB, InC, InD, InE>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e,
&out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
template<class ObjT, class Method,
@ -1079,10 +1315,19 @@ template<class ObjT, class Method,
inline void DispatchToMethod(ObjT* obj, Method method,
const Tuple6<InA, InB, InC, InD, InE, InF>& in,
Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
(obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f,
&out->a, &out->b, &out->c, &out->d, &out->e);
(obj->*method)(base::internal::UnwrapTraits<InA>::Unwrap(in.a),
base::internal::UnwrapTraits<InB>::Unwrap(in.b),
base::internal::UnwrapTraits<InC>::Unwrap(in.c),
base::internal::UnwrapTraits<InD>::Unwrap(in.d),
base::internal::UnwrapTraits<InE>::Unwrap(in.e),
base::internal::UnwrapTraits<InF>::Unwrap(in.f),
&out->a,
&out->b,
&out->c,
&out->d,
&out->e);
}
#endif // BASE_TUPLE_H__
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_
#endif // CEF_INCLUDE_BASE_CEF_TUPLE_H_

382
include/base/cef_weak_ptr.h Normal file
View 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 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, 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 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 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_ = 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 internal::SupportsWeakPtrBase;
template <typename U> friend class WeakPtr;
friend class SupportsWeakPtr<T>;
friend class WeakPtrFactory<T>;
WeakPtr(const 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:
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 internal::SupportsWeakPtrBase {
public:
SupportsWeakPtr() {}
WeakPtr<T> AsWeakPtr() {
return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
}
protected:
~SupportsWeakPtr() {}
private:
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 internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
}
} // namespace base
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_

View 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_

View 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_

View 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_

View 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_

File diff suppressed because it is too large Load Diff

View 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 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 internal
} // namespace base
#endif // !defined(ARCH_CPU_X86_64)
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_

View 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 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;
// 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 internal
} // namespace base
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_

View 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 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 internal
} // namespace base
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_

View 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 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 internal
} // namespace base
#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_

View 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_

View File

@ -55,20 +55,22 @@ typedef struct _cef_base_t {
size_t size;
///
// Increment the reference count.
// Called to increment the reference count for the object. Should be called
// for every new copy of a pointer to a given object.
///
int (CEF_CALLBACK *add_ref)(struct _cef_base_t* self);
void (CEF_CALLBACK *add_ref)(struct _cef_base_t* self);
///
// Decrement the reference count. Delete this object when no references
// remain.
// Called to decrement the reference count for the object. If the reference
// count falls to 0 the object should self-delete. Returns true (1) if the
// resulting reference count is 0.
///
int (CEF_CALLBACK *release)(struct _cef_base_t* self);
///
// Returns the current number of references.
// Returns true (1) if the current reference count is 1.
///
int (CEF_CALLBACK *get_refct)(struct _cef_base_t* self);
int (CEF_CALLBACK *has_one_ref)(struct _cef_base_t* self);
} cef_base_t;

View File

@ -26,24 +26,19 @@
// 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 must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_BASE_H_
#define CEF_INCLUDE_CEF_BASE_H_
#pragma once
#include "include/base/cef_atomic_ref_count.h"
#include "include/base/cef_build.h"
#include "include/base/cef_macros.h"
// Bring in common C++ type definitions used by CEF consumers.
#include "include/internal/cef_ptr.h"
#include "include/internal/cef_types_wrappers.h"
// Bring in platform-specific definitions.
#if defined(OS_WIN)
#include "include/internal/cef_win.h"
#elif defined(OS_MACOSX)
@ -59,59 +54,57 @@
class CefBase {
public:
///
// The AddRef method increments the reference count for the object. It should
// be called for every new copy of a pointer to a given object. The resulting
// reference count value is returned and should be used for diagnostic/testing
// purposes only.
// Called to increment the reference count for the object. Should be called
// for every new copy of a pointer to a given object.
///
virtual int AddRef() =0;
virtual void AddRef() const =0;
///
// The Release method decrements the reference count for the object. If the
// reference count on the object falls to 0, then the object should free
// itself from memory. The resulting reference count value is returned and
// should be used for diagnostic/testing purposes only.
// Called to decrement the reference count for the object. Returns true if
// the reference count is 0, in which case the object should self-delete.
///
virtual int Release() =0;
virtual bool Release() const =0;
///
// Return the current number of references.
// Returns true if the reference count is 1.
///
virtual int GetRefCt() =0;
virtual bool HasOneRef() const =0;
protected:
virtual ~CefBase() {}
};
///
// Class that implements atomic reference counting.
///
class CefRefCount {
public:
CefRefCount() : refct_(0) {}
CefRefCount() : ref_count_(0) {}
///
// Atomic reference increment.
// Increment the reference count.
///
int AddRef() {
return CefAtomicIncrement(&refct_);
void AddRef() const {
base::AtomicRefCountInc(&ref_count_);
}
///
// Atomic reference decrement. Delete the object when no references remain.
// Decrement the reference count. Returns true if the reference count is 0.
///
int Release() {
return CefAtomicDecrement(&refct_);
bool Release() const {
return !base::AtomicRefCountDec(&ref_count_);
}
///
// Return the current number of references.
// Returns true if the reference count is 1.
///
int GetRefCt() { return refct_; }
bool HasOneRef() const {
return base::AtomicRefCountIsOne(&ref_count_);
}
private:
long refct_; // NOLINT(runtime/int)
mutable base::AtomicRefCount ref_count_;
DISALLOW_COPY_AND_ASSIGN(CefRefCount);
};
///
@ -120,22 +113,54 @@ class CefRefCount {
///
#define IMPLEMENT_REFCOUNTING(ClassName) \
public: \
int AddRef() { return refct_.AddRef(); } \
int Release() { \
int retval = refct_.Release(); \
if (retval == 0) \
delete this; \
return retval; \
void AddRef() const { \
ref_count_.AddRef(); \
} \
bool Release() const { \
if (ref_count_.Release()) { \
delete static_cast<const ClassName*>(this); \
return true; \
} \
return false; \
} \
bool HasOneRef() const { \
return ref_count_.HasOneRef(); \
} \
int GetRefCt() { return refct_.GetRefCt(); } \
private: \
CefRefCount refct_;
CefRefCount ref_count_;
///
// Macro that provides a locking implementation. Use the Lock() and Unlock()
// methods to protect a section of code from simultaneous access by multiple
// threads. The AutoLock class is a helper that will hold the lock while in
// scope.
//
// THIS MACRO IS DEPRECATED. Use an explicit base::Lock member variable and
// base::AutoLock instead. For example:
//
// #include "include/base/cef_lock.h"
//
// // Class declaration.
// class MyClass : public CefBase {
// public:
// MyClass() : value_(0) {}
// // Method that may be called on multiple threads.
// void IncrementValue();
// private:
// // Value that may be accessed on multiple theads.
// int value_;
// // Lock used to protect access to |value_|.
// base::Lock lock_;
// IMPLEMENT_REFCOUNTING(MyClass);
// };
//
// // Class implementation.
// void MyClass::IncrementValue() {
// // Acquire the lock for the scope of this method.
// base::AutoLock lock_scope(lock_);
// // |value_| can now be modified safely.
// value_++;
// }
///
#define IMPLEMENT_LOCKING(ClassName) \
public: \
@ -145,10 +170,11 @@ class CefRefCount {
~AutoLock() { base_->Unlock(); } \
private: \
ClassName* base_; \
DISALLOW_COPY_AND_ASSIGN(AutoLock); \
}; \
void Lock() { critsec_.Lock(); } \
void Unlock() { critsec_.Unlock(); } \
void Lock() { lock_.Acquire(); } \
void Unlock() { lock_.Release(); } \
private: \
CefCriticalSection critsec_;
base::Lock lock_;
#endif // CEF_INCLUDE_CEF_BASE_H_

View File

@ -34,13 +34,9 @@
#define CEF_INCLUDE_CEF_RUNNABLE_H_
#pragma once
#include "include/base/cef_tuple.h"
#include "include/cef_base.h"
#include "include/cef_task.h"
#ifdef BUILDING_CEF_SHARED
#include "base/tuple.h"
#else
#include "internal/cef_tuple.h"
#endif
// CefRunnableMethodTraits -----------------------------------------------------
//

View File

@ -79,7 +79,7 @@ class CefEndTracingCallback : public virtual CefBase {
//
// This function must be called on the browser process UI thread.
///
/*--cef(optional_param=categories)--*/
/*--cef(optional_param=categories,optional_param=callback)--*/
bool CefBeginTracing(const CefString& categories,
CefRefPtr<CefCompletionCallback> callback);

View File

@ -32,42 +32,9 @@
#define CEF_INCLUDE_INTERNAL_CEF_LINUX_H_
#pragma once
#if defined(OS_LINUX)
#include <pthread.h>
#include "include/internal/cef_types_linux.h"
#include "include/internal/cef_types_wrappers.h"
// Atomic increment and decrement.
inline long CefAtomicIncrement(long volatile *pDest) { // NOLINT(runtime/int)
return __sync_add_and_fetch(pDest, 1);
}
inline long CefAtomicDecrement(long volatile *pDest) { // NOLINT(runtime/int)
return __sync_sub_and_fetch(pDest, 1);
}
// Critical section wrapper.
class CefCriticalSection {
public:
CefCriticalSection() {
pthread_mutexattr_init(&attr_);
pthread_mutexattr_settype(&attr_, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lock_, &attr_);
}
virtual ~CefCriticalSection() {
pthread_mutex_destroy(&lock_);
pthread_mutexattr_destroy(&attr_);
}
void Lock() {
pthread_mutex_lock(&lock_);
}
void Unlock() {
pthread_mutex_unlock(&lock_);
}
pthread_mutex_t lock_;
pthread_mutexattr_t attr_;
};
// Handle types.
#define CefCursorHandle cef_cursor_handle_t
#define CefEventHandle cef_event_handle_t
@ -160,6 +127,4 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
}
};
#endif // OS_LINUX
#endif // CEF_INCLUDE_INTERNAL_CEF_LINUX_H_

View File

@ -32,42 +32,9 @@
#define CEF_INCLUDE_INTERNAL_CEF_MAC_H_
#pragma once
#if defined(OS_MACOSX)
#include <pthread.h>
#include "include/internal/cef_types_mac.h"
#include "include/internal/cef_types_wrappers.h"
// Atomic increment and decrement.
inline long CefAtomicIncrement(long volatile *pDest) { // NOLINT(runtime/int)
return __sync_add_and_fetch(pDest, 1);
}
inline long CefAtomicDecrement(long volatile *pDest) { // NOLINT(runtime/int)
return __sync_sub_and_fetch(pDest, 1);
}
// Critical section wrapper.
class CefCriticalSection {
public:
CefCriticalSection() {
pthread_mutexattr_init(&attr_);
pthread_mutexattr_settype(&attr_, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lock_, &attr_);
}
virtual ~CefCriticalSection() {
pthread_mutex_destroy(&lock_);
pthread_mutexattr_destroy(&attr_);
}
void Lock() {
pthread_mutex_lock(&lock_);
}
void Unlock() {
pthread_mutex_unlock(&lock_);
}
pthread_mutex_t lock_;
pthread_mutexattr_t attr_;
};
// Handle types.
#define CefCursorHandle cef_cursor_handle_t
#define CefEventHandle cef_event_handle_t
@ -167,6 +134,4 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
}
};
#endif // OS_MACOSX
#endif // CEF_INCLUDE_INTERNAL_CEF_MAC_H_

View File

@ -1,5 +1,4 @@
// Copyright (c) 2008 Marshall A. Greenblatt. Portions Copyright (c)
// 2006-2008 Google Inc. All rights reserved.
// Copyright (c) 2014 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
@ -33,10 +32,11 @@
#define CEF_INCLUDE_INTERNAL_CEF_PTR_H_
#pragma once
#include <stddef.h>
#include "include/base/cef_ref_counted.h"
///
// Smart pointer implementation borrowed from base/ref_counted.h
// Smart pointer implementation that is an alias of scoped_refptr from
// include/base/cef_ref_counted.h.
// <p>
// A smart pointer class for reference counted objects. Use this class instead
// of calling AddRef and Release manually on a reference counted object to
@ -144,56 +144,18 @@
// </p>
///
template <class T>
class CefRefPtr {
class CefRefPtr : public scoped_refptr<T> {
public:
CefRefPtr() : ptr_(NULL) {
}
typedef scoped_refptr<T> parent;
CefRefPtr(T* p) : ptr_(p) { // NOLINT(runtime/explicit)
if (ptr_)
ptr_->AddRef();
}
CefRefPtr() : parent() {}
CefRefPtr(const CefRefPtr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
ptr_->AddRef();
}
CefRefPtr(T* p) : parent(p) {}
~CefRefPtr() {
if (ptr_)
ptr_->Release();
}
CefRefPtr(const scoped_refptr<T>& r) : parent(r) {}
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
T* operator->() const { return ptr_; }
CefRefPtr<T>& operator=(T* p) {
// AddRef first so that self assignment should work
if (p)
p->AddRef();
if (ptr_ )
ptr_ ->Release();
ptr_ = p;
return *this;
}
CefRefPtr<T>& operator=(const CefRefPtr<T>& r) {
return *this = r.ptr_;
}
void swap(T** pp) {
T* p = ptr_;
ptr_ = *pp;
*pp = p;
}
void swap(CefRefPtr<T>& r) {
swap(&r.ptr_); // NOLINT(build/include_what_you_use)
}
private:
T* ptr_;
template <typename U>
CefRefPtr(const scoped_refptr<U>& r) : parent(r) {}
};
#endif // CEF_INCLUDE_INTERNAL_CEF_PTR_H_

View File

@ -0,0 +1,74 @@
// Copyright (c) 2014 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_INTERNAL_CEF_THREAD_INTERNAL_H_
#define CEF_INCLUDE_INTERNAL_CEF_THREAD_INTERNAL_H_
#pragma once
#if defined(OS_WIN)
#include <windows.h>
#elif defined(OS_POSIX)
#include <pthread.h>
#include <unistd.h>
#endif
#include "include/internal/cef_export.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(OS_WIN)
typedef DWORD cef_platform_thread_id_t;
#elif defined(OS_POSIX)
typedef pid_t cef_platform_thread_id_t;
#endif
///
// Returns the current platform thread ID.
///
CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id();
#if defined(OS_WIN)
typedef DWORD cef_platform_thread_handle_t;
#elif defined(OS_POSIX)
typedef pthread_t cef_platform_thread_handle_t;
#endif
///
// Returns the current platform thread handle.
///
CEF_EXPORT cef_platform_thread_handle_t
cef_get_current_platform_thread_handle();
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // CEF_INCLUDE_INTERNAL_CEF_THREAD_INTERNAL_H_

View File

@ -32,39 +32,9 @@
#define CEF_INCLUDE_INTERNAL_CEF_WIN_H_
#pragma once
#if defined(OS_WIN)
#include <windows.h>
#include "include/internal/cef_types_win.h"
#include "include/internal/cef_types_wrappers.h"
///
// Atomic increment and decrement.
///
#define CefAtomicIncrement(p) InterlockedIncrement(p)
#define CefAtomicDecrement(p) InterlockedDecrement(p)
///
// Critical section wrapper.
///
class CefCriticalSection {
public:
CefCriticalSection() {
memset(&m_sec, 0, sizeof(CRITICAL_SECTION));
InitializeCriticalSection(&m_sec);
}
virtual ~CefCriticalSection() {
DeleteCriticalSection(&m_sec);
}
void Lock() {
EnterCriticalSection(&m_sec);
}
void Unlock() {
LeaveCriticalSection(&m_sec);
}
CRITICAL_SECTION m_sec;
};
///
// Handle types.
///
@ -183,6 +153,4 @@ class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
}
};
#endif // OS_WIN
#endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_

View File

@ -37,6 +37,7 @@
#define CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_
#pragma once
#include "include/base/cef_lock.h"
#include "include/base/cef_macros.h"
#include "include/cef_base.h"
#include "include/cef_stream.h"
@ -69,9 +70,9 @@ class CefByteReadHandler : public CefReadHandler {
int64 offset_;
CefRefPtr<CefBase> source_;
IMPLEMENT_REFCOUNTING(CefByteReadHandler);
IMPLEMENT_LOCKING(CefByteReadHandler);
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefByteReadHandler);
DISALLOW_COPY_AND_ASSIGN(CefByteReadHandler);
};

View File

@ -0,0 +1,101 @@
// Copyright (c) 2014 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.
//
// ---------------------------------------------------------------------------
//
// The contents of this file are only available to applications that link
// against the libcef_dll_wrapper target.
//
#ifndef CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_
#define CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_
#pragma once
#include "include/base/cef_callback_forward.h"
#include "include/base/cef_macros.h"
#include "include/cef_task.h"
///
// Helpers for asynchronously executing a base::Closure (bound function or
// method) on a CEF thread. Creation of base::Closures can be facilitated using
// base::Bind. See include/base/cef_callback.h for complete usage instructions.
//
// TO use these helpers you should include this header and the header that
// defines base::Bind.
//
// #include "include/base/cef_bind.h"
// #include "include/wrapper/cef_closure_task.h"
//
// Example of executing a bound function:
//
// // Define a function.
// void MyFunc(int arg) { /* do something with |arg| on the UI thread */ }
//
// // Post a task that will execute MyFunc on the UI thread and pass an |arg|
// // value of 5.
// CefPostTask(TID_UI, base::Bind(&MyFunc, 5));
//
// Example of executing a bound method:
//
// // Define a class.
// class MyClass : public CefBase {
// public:
// MyClass() {}
// void MyMethod(int arg) { /* do something with |arg| on the UI thread */ }
// private:
// IMPLEMENT_REFOCUNTING(MyClass);
// };
//
// // Create an instance of MyClass.
// CefRefPtr<MyClass> instance = new MyClass();
//
// // Post a task that will execute MyClass::MyMethod on the UI thread and pass
// // an |arg| value of 5. |instance| will be kept alive until after the task
// // completes.
// CefPostTask(TID_UI, base::Bind(&MyClass::MyMethod, instance, 5));
///
///
// Create a CefTask that wraps a base::Closure. Can be used in combination with
// CefTaskRunner.
///
CefRefPtr<CefTask> CefCreateClosureRask(const base::Closure& closure);
///
// Post a Closure for execution on the specified thread.
///
bool CefPostTask(CefThreadId threadId, const base::Closure& closure);
///
// Post a Closure for delayed execution on the specified thread.
///
bool CefPostDelayedTask(CefThreadId threadId, const base::Closure& closure,
int64 delay_ms);
#endif // CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_

View File

@ -50,7 +50,9 @@
#define CEF_REQUIRE_FILE_THREAD() DCHECK(CefCurrentlyOn(TID_FILE));
#define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER));
///
// Helper class to manage a scoped copy of |argv|.
///
class CefScopedArgArray {
public:
CefScopedArgArray(int argc, char* argv[]) {

View File

@ -97,7 +97,6 @@ class CefStreamResourceHandler : public CefResourceHandler {
#endif
IMPLEMENT_REFCOUNTING(CefStreamResourceHandler);
DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler);
};

View File

@ -37,6 +37,7 @@
#define CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_
#pragma once
#include "include/base/cef_lock.h"
#include "include/base/cef_macros.h"
#include "include/cef_base.h"
#include "include/cef_xml_reader.h"
@ -182,9 +183,9 @@ class CefXmlObject : public CefBase {
AttributeMap attributes_;
ObjectVector children_;
IMPLEMENT_REFCOUNTING(CefXmlObject);
IMPLEMENT_LOCKING(CefXmlObject);
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefXmlObject);
DISALLOW_COPY_AND_ASSIGN(CefXmlObject);
};

View File

@ -37,6 +37,7 @@
#define CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_
#pragma once
#include "include/base/cef_lock.h"
#include "include/base/cef_macros.h"
#include "include/cef_base.h"
#include <map>
@ -129,9 +130,9 @@ class CefZipArchive : public CefBase {
private:
FileMap contents_;
IMPLEMENT_REFCOUNTING(CefZipArchive);
IMPLEMENT_LOCKING(CefZipArchive);
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefZipArchive);
DISALLOW_COPY_AND_ASSIGN(CefZipArchive);
};

View File

@ -1803,7 +1803,7 @@ void CefBrowserHostImpl::DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
}
CefDragDataImpl* data_impl = static_cast<CefDragDataImpl*>(drag_data.get());
CefDragDataImpl::AutoLock lock_scope(data_impl);
base::AutoLock lock_scope(data_impl->lock());
const content::DropData& drop_data = data_impl->drop_data();
gfx::Point client_pt(event.x, event.y);
gfx::Point screen_pt(screenX, screenY);

View File

@ -89,7 +89,7 @@ bool CefMenuCreator::CreateContextMenu(
// Do not keep references to the parameters in the callback.
paramsPtr->Detach(NULL);
DCHECK_EQ(paramsPtr->GetRefCt(), 1);
DCHECK(paramsPtr->HasOneRef());
DCHECK(model_->VerifyRefCount());
// Menu is empty so notify the client and return.
@ -146,7 +146,7 @@ void CefMenuCreator::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
// Do not keep references to the parameters in the callback.
paramsPtr->Detach(NULL);
DCHECK_EQ(paramsPtr->GetRefCt(), 1);
DCHECK(paramsPtr->HasOneRef());
if (handled)
return;

View File

@ -651,7 +651,7 @@ bool CefMenuModelImpl::VerifyRefCount() {
if (!VerifyContext())
return false;
if (GetRefCt() != 1)
if (!HasOneRef())
return false;
for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {

View File

@ -143,7 +143,7 @@ class CefResourceRequestJobCallback : public CefCallback {
net::IOBuffer* dest_;
int dest_size_;
IMPLEMENT_REFCOUNTING(Callback);
IMPLEMENT_REFCOUNTING(CefResourceRequestJobCallback);
};
CefResourceRequestJob::CefResourceRequestJob(

View File

@ -74,18 +74,18 @@ CefFileReader::CefFileReader(FILE* file, bool close)
}
CefFileReader::~CefFileReader() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (close_)
base::CloseFile(file_);
}
size_t CefFileReader::Read(void* ptr, size_t size, size_t n) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return fread(ptr, size, n, file_);
}
int CefFileReader::Seek(int64 offset, int whence) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
#if defined(OS_WIN)
return _fseeki64(file_, offset, whence);
#else
@ -94,7 +94,7 @@ int CefFileReader::Seek(int64 offset, int whence) {
}
int64 CefFileReader::Tell() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
#if defined(OS_WIN)
return _ftelli64(file_);
#else
@ -103,7 +103,7 @@ int64 CefFileReader::Tell() {
}
int CefFileReader::Eof() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return feof(file_);
}
@ -116,28 +116,28 @@ CefFileWriter::CefFileWriter(FILE* file, bool close)
}
CefFileWriter::~CefFileWriter() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (close_)
base::CloseFile(file_);
}
size_t CefFileWriter::Write(const void* ptr, size_t size, size_t n) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return (size_t)fwrite(ptr, size, n, file_);
}
int CefFileWriter::Seek(int64 offset, int whence) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return fseek(file_, offset, whence);
}
int64 CefFileWriter::Tell() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return ftell(file_);
}
int CefFileWriter::Flush() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return fflush(file_);
}
@ -157,7 +157,7 @@ CefBytesReader::~CefBytesReader() {
}
size_t CefBytesReader::Read(void* ptr, size_t size, size_t n) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
size_t s = (datasize_ - offset_) / size;
size_t ret = (n < s ? n : s);
memcpy(ptr, (reinterpret_cast<char*>(data_)) + offset_, ret * size);
@ -167,7 +167,7 @@ size_t CefBytesReader::Read(void* ptr, size_t size, size_t n) {
int CefBytesReader::Seek(int64 offset, int whence) {
int rv = -1L;
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
switch (whence) {
case SEEK_CUR:
if (offset_ + offset > datasize_ || offset_ + offset < 0)
@ -195,17 +195,17 @@ int CefBytesReader::Seek(int64 offset, int whence) {
}
int64 CefBytesReader::Tell() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return offset_;
}
int CefBytesReader::Eof() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return (offset_ >= datasize_);
}
void CefBytesReader::SetData(void* data, int64 datasize, bool copy) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (copy_)
free(data_);
@ -236,13 +236,13 @@ CefBytesWriter::CefBytesWriter(size_t grow)
}
CefBytesWriter::~CefBytesWriter() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (data_)
free(data_);
}
size_t CefBytesWriter::Write(const void* ptr, size_t size, size_t n) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
size_t rv;
if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
Grow(size * n) == 0) {
@ -258,7 +258,7 @@ size_t CefBytesWriter::Write(const void* ptr, size_t size, size_t n) {
int CefBytesWriter::Seek(int64 offset, int whence) {
int rv = -1L;
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
switch (whence) {
case SEEK_CUR:
if (offset_ + offset > datasize_ || offset_ + offset < 0)
@ -286,7 +286,7 @@ int CefBytesWriter::Seek(int64 offset, int whence) {
}
int64 CefBytesWriter::Tell() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return offset_;
}
@ -295,13 +295,13 @@ int CefBytesWriter::Flush() {
}
std::string CefBytesWriter::GetDataString() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
std::string str(reinterpret_cast<char*>(data_), offset_);
return str;
}
size_t CefBytesWriter::Grow(size_t size) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
size_t rv;
size_t s = (size > grow_ ? size : grow_);
void* tmp = realloc(data_, datasize_ + s);

View File

@ -6,9 +6,12 @@
#define CEF_LIBCEF_BROWSER_STREAM_IMPL_H_
#pragma once
#include "include/cef_stream.h"
#include <stdio.h>
#include <string>
#include "include/cef_stream.h"
#include "base/synchronization/lock.h"
// Implementation of CefStreamReader for files.
class CefFileReader : public CefStreamReader {
@ -26,8 +29,9 @@ class CefFileReader : public CefStreamReader {
bool close_;
FILE* file_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefFileReader);
IMPLEMENT_LOCKING(CefFileReader);
};
// Implementation of CefStreamWriter for files.
@ -46,8 +50,9 @@ class CefFileWriter : public CefStreamWriter {
FILE* file_;
bool close_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefFileWriter);
IMPLEMENT_LOCKING(CefFileWriter);
};
// Implementation of CefStreamReader for byte buffers.
@ -73,8 +78,9 @@ class CefBytesReader : public CefStreamReader {
bool copy_;
int64 offset_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefBytesReader);
IMPLEMENT_LOCKING(CefBytesReader);
};
// Implementation of CefStreamWriter for byte buffers.
@ -101,8 +107,9 @@ class CefBytesWriter : public CefStreamWriter {
int64 datasize_;
int64 offset_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefBytesWriter);
IMPLEMENT_LOCKING(CefBytesWriter);
};
// Implementation of CefStreamReader for handlers.

View File

@ -67,7 +67,7 @@ class CefXmlReaderImpl : public CefXmlReader {
xmlTextReaderPtr reader_;
std::stringstream error_buf_;
IMPLEMENT_REFCOUNTING(CefXMLReaderImpl);
IMPLEMENT_REFCOUNTING(CefXmlReaderImpl);
};
#endif // CEF_LIBCEF_BROWSER_XML_READER_IMPL_H_

View File

@ -4,9 +4,11 @@
#include "include/internal/cef_trace_event_internal.h"
#include "include/internal/cef_logging_internal.h"
#include "include/internal/cef_thread_internal.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/threading/platform_thread.h"
// The contents of this file are a compilation unit that is not called by other
// functions in the the library. Consiquently MSVS will exclude it during the
@ -328,3 +330,16 @@ CEF_EXPORT void cef_log(const char* file,
const char* message) {
logging::LogMessage(file, line, severity).stream() << message;
}
CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id() {
return base::PlatformThread::CurrentId();
}
CEF_EXPORT cef_platform_thread_handle_t
cef_get_current_platform_thread_handle() {
#if defined(OS_WIN)
return base::PlatformThread::CurrentId();
#else
return base::PlatformThread::CurrentHandle().platform_handle();
#endif
}

View File

@ -32,65 +32,65 @@ CefRefPtr<CefDragData> CefDragData::Create() {
CefRefPtr<CefDragData> CefDragDataImpl::Clone() {
CefDragDataImpl* drag_data = NULL;
{
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
drag_data = new CefDragDataImpl(data_);
}
return drag_data;
}
bool CefDragDataImpl::IsReadOnly() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return read_only_;
}
bool CefDragDataImpl::IsLink() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return (data_.url.is_valid() && data_.file_description_filename.empty());
}
bool CefDragDataImpl::IsFragment() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return (!data_.url.is_valid() && data_.file_description_filename.empty() &&
data_.filenames.empty());
}
bool CefDragDataImpl::IsFile() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return (!data_.file_description_filename.empty() || !data_.filenames.empty());
}
CefString CefDragDataImpl::GetLinkURL() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.url.spec();
}
CefString CefDragDataImpl::GetLinkTitle() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.url_title;
}
CefString CefDragDataImpl::GetLinkMetadata() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.download_metadata;
}
CefString CefDragDataImpl::GetFragmentText() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.text.is_null() ? CefString() : CefString(data_.text.string());
}
CefString CefDragDataImpl::GetFragmentHtml() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.html.is_null() ? CefString() : CefString(data_.html.string());
}
CefString CefDragDataImpl::GetFragmentBaseURL() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return data_.html_base_url.spec();
}
CefString CefDragDataImpl::GetFileName() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (data_.file_description_filename.empty())
return CefString();
@ -108,7 +108,7 @@ CefString CefDragDataImpl::GetFileName() {
}
size_t CefDragDataImpl::GetFileContents(CefRefPtr<CefStreamWriter> writer) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (data_.file_contents.empty())
return 0;
@ -122,7 +122,7 @@ size_t CefDragDataImpl::GetFileContents(CefRefPtr<CefStreamWriter> writer) {
}
bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (data_.filenames.empty())
return false;
@ -135,43 +135,43 @@ bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names) {
}
void CefDragDataImpl::SetLinkURL(const CefString& url) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.url = GURL(url.ToString());
}
void CefDragDataImpl::SetLinkTitle(const CefString& title) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.url_title = title.ToString16();
}
void CefDragDataImpl::SetLinkMetadata(const CefString& data) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.download_metadata = data.ToString16();
}
void CefDragDataImpl::SetFragmentText(const CefString& text) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.text = base::NullableString16(text.ToString16(), false);
}
void CefDragDataImpl::SetFragmentHtml(const CefString& fragment) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.html = base::NullableString16(fragment.ToString16(), false);
}
void CefDragDataImpl::SetFragmentBaseURL(const CefString& fragment) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.html_base_url = GURL(fragment.ToString());
}
void CefDragDataImpl::ResetFileContents() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.file_contents.erase();
data_.file_description_filename.erase();
@ -179,14 +179,14 @@ void CefDragDataImpl::ResetFileContents() {
void CefDragDataImpl::AddFile(const CefString& path,
const CefString& display_name) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
data_.filenames.push_back(ui::FileInfo(base::FilePath(path),
base::FilePath(display_name)));
}
void CefDragDataImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (read_only_ == read_only)
return;

View File

@ -6,9 +6,11 @@
#define CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_
#pragma once
#include "include/cef_drag_data.h"
#include <vector>
#include "include/cef_drag_data.h"
#include "base/synchronization/lock.h"
#include "content/public/common/drop_data.h"
// Implementation of CefDragData.
@ -48,14 +50,17 @@ class CefDragDataImpl : public CefDragData {
void SetReadOnly(bool read_only);
protected:
base::Lock& lock() { return lock_; }
private:
content::DropData data_;
// True if this object is read-only.
bool read_only_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefDragDataImpl);
IMPLEMENT_LOCKING(CefDragDataImpl);
};
#endif // CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_

View File

@ -112,50 +112,50 @@ CefRequestImpl::CefRequestImpl()
}
bool CefRequestImpl::IsReadOnly() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return read_only_;
}
CefString CefRequestImpl::GetURL() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return url_;
}
void CefRequestImpl::SetURL(const CefString& url) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
url_ = url;
}
CefString CefRequestImpl::GetMethod() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return method_;
}
void CefRequestImpl::SetMethod(const CefString& method) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
method_ = method;
}
CefRefPtr<CefPostData> CefRequestImpl::GetPostData() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return postdata_;
}
void CefRequestImpl::SetPostData(CefRefPtr<CefPostData> postData) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
postdata_ = postData;
}
void CefRequestImpl::GetHeaderMap(HeaderMap& headerMap) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
headerMap = headermap_;
}
void CefRequestImpl::SetHeaderMap(const HeaderMap& headerMap) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
headermap_ = headerMap;
}
@ -164,7 +164,7 @@ void CefRequestImpl::Set(const CefString& url,
const CefString& method,
CefRefPtr<CefPostData> postData,
const HeaderMap& headerMap) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
url_ = url;
method_ = method;
@ -173,37 +173,37 @@ void CefRequestImpl::Set(const CefString& url,
}
int CefRequestImpl::GetFlags() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return flags_;
}
void CefRequestImpl::SetFlags(int flags) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
flags_ = flags;
}
CefString CefRequestImpl::GetFirstPartyForCookies() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return first_party_for_cookies_;
}
void CefRequestImpl::SetFirstPartyForCookies(const CefString& url) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
first_party_for_cookies_ = url;
}
CefRequestImpl::ResourceType CefRequestImpl::GetResourceType() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return resource_type_;
}
CefRequestImpl::TransitionType CefRequestImpl::GetTransitionType() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return transition_type_;
}
void CefRequestImpl::Set(net::URLRequest* request) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
url_ = request->url().spec();
@ -252,7 +252,7 @@ void CefRequestImpl::Set(net::URLRequest* request) {
}
void CefRequestImpl::Get(net::URLRequest* request) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
request->set_method(method_);
if (!first_party_for_cookies_.empty()) {
@ -285,7 +285,7 @@ void CefRequestImpl::Get(net::URLRequest* request) {
void CefRequestImpl::Set(const blink::WebURLRequest& request) {
DCHECK(!request.isNull());
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
url_ = request.url().spec().utf16();
@ -320,7 +320,7 @@ void CefRequestImpl::Set(const blink::WebURLRequest& request) {
void CefRequestImpl::Get(blink::WebURLRequest& request) {
request.initialize();
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
GURL gurl = GURL(url_.ToString());
request.setURL(blink::WebURL(gurl));
@ -359,7 +359,7 @@ void CefRequestImpl::Get(blink::WebURLRequest& request) {
}
void CefRequestImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (read_only_ == read_only)
return;
@ -428,22 +428,22 @@ CefPostDataImpl::CefPostDataImpl()
}
bool CefPostDataImpl::IsReadOnly() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return read_only_;
}
size_t CefPostDataImpl::GetElementCount() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return elements_.size();
}
void CefPostDataImpl::GetElements(ElementVector& elements) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
elements = elements_;
}
bool CefPostDataImpl::RemoveElement(CefRefPtr<CefPostDataElement> element) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN(false);
ElementVector::iterator it = elements_.begin();
@ -460,7 +460,7 @@ bool CefPostDataImpl::RemoveElement(CefRefPtr<CefPostDataElement> element) {
bool CefPostDataImpl::AddElement(CefRefPtr<CefPostDataElement> element) {
bool found = false;
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN(false);
// check that the element isn't already in the list before adding
@ -479,14 +479,16 @@ bool CefPostDataImpl::AddElement(CefRefPtr<CefPostDataElement> element) {
}
void CefPostDataImpl::RemoveElements() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
elements_.clear();
}
void CefPostDataImpl::Set(const net::UploadData& data) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
CefRefPtr<CefPostDataElement> postelem;
@ -500,8 +502,10 @@ void CefPostDataImpl::Set(const net::UploadData& data) {
}
void CefPostDataImpl::Set(const net::UploadDataStream& data_stream) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
CefRefPtr<CefPostDataElement> postelem;
@ -516,7 +520,7 @@ void CefPostDataImpl::Set(const net::UploadDataStream& data_stream) {
}
void CefPostDataImpl::Get(net::UploadData& data) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
ScopedVector<net::UploadElement> data_elements;
ElementVector::const_iterator it = elements_.begin();
@ -529,7 +533,7 @@ void CefPostDataImpl::Get(net::UploadData& data) {
}
net::UploadDataStream* CefPostDataImpl::Get() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
ScopedVector<net::UploadElementReader> element_readers;
ElementVector::const_iterator it = elements_.begin();
@ -542,8 +546,10 @@ net::UploadDataStream* CefPostDataImpl::Get() {
}
void CefPostDataImpl::Set(const blink::WebHTTPBody& data) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
CefRefPtr<CefPostDataElement> postelem;
blink::WebHTTPBody::Element element;
@ -558,7 +564,7 @@ void CefPostDataImpl::Set(const blink::WebHTTPBody& data) {
}
void CefPostDataImpl::Get(blink::WebHTTPBody& data) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
blink::WebHTTPBody::Element element;
ElementVector::iterator it = elements_.begin();
@ -575,7 +581,7 @@ void CefPostDataImpl::Get(blink::WebHTTPBody& data) {
}
void CefPostDataImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (read_only_ == read_only)
return;
@ -609,23 +615,23 @@ CefPostDataElementImpl::~CefPostDataElementImpl() {
}
bool CefPostDataElementImpl::IsReadOnly() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return read_only_;
}
void CefPostDataElementImpl::SetToEmpty() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
Cleanup();
}
void CefPostDataElementImpl::SetToFile(const CefString& fileName) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
// Clear any data currently in the element
SetToEmpty();
Cleanup();
// Assign the new data
type_ = PDE_TYPE_FILE;
@ -633,11 +639,11 @@ void CefPostDataElementImpl::SetToFile(const CefString& fileName) {
}
void CefPostDataElementImpl::SetToBytes(size_t size, const void* bytes) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
// Clear any data currently in the element
SetToEmpty();
Cleanup();
// Assign the new data
void* data = malloc(size);
@ -653,12 +659,12 @@ void CefPostDataElementImpl::SetToBytes(size_t size, const void* bytes) {
}
CefPostDataElement::Type CefPostDataElementImpl::GetType() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return type_;
}
CefString CefPostDataElementImpl::GetFile() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
DCHECK(type_ == PDE_TYPE_FILE);
CefString filename;
if (type_ == PDE_TYPE_FILE)
@ -667,7 +673,7 @@ CefString CefPostDataElementImpl::GetFile() {
}
size_t CefPostDataElementImpl::GetBytesCount() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
DCHECK(type_ == PDE_TYPE_BYTES);
size_t size = 0;
if (type_ == PDE_TYPE_BYTES)
@ -676,7 +682,7 @@ size_t CefPostDataElementImpl::GetBytesCount() {
}
size_t CefPostDataElementImpl::GetBytes(size_t size, void* bytes) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
DCHECK(type_ == PDE_TYPE_BYTES);
size_t rv = 0;
if (type_ == PDE_TYPE_BYTES) {
@ -687,8 +693,10 @@ size_t CefPostDataElementImpl::GetBytes(size_t size, void* bytes) {
}
void CefPostDataElementImpl::Set(const net::UploadElement& element) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
if (element.type() == net::UploadElement::TYPE_BYTES) {
SetToBytes(element.bytes_length(), element.bytes());
@ -701,8 +709,10 @@ void CefPostDataElementImpl::Set(const net::UploadElement& element) {
void CefPostDataElementImpl::Set(
const net::UploadElementReader& element_reader) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
const net::UploadBytesElementReader* bytes_reader =
element_reader.AsBytesReader();
@ -722,7 +732,7 @@ void CefPostDataElementImpl::Set(
}
void CefPostDataElementImpl::Get(net::UploadElement& element) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (type_ == PDE_TYPE_BYTES) {
element.SetToBytes(static_cast<char*>(data_.bytes.bytes), data_.bytes.size);
@ -735,7 +745,7 @@ void CefPostDataElementImpl::Get(net::UploadElement& element) {
}
net::UploadElementReader* CefPostDataElementImpl::Get() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (type_ == PDE_TYPE_BYTES) {
net::UploadElement* element = new net::UploadElement();
@ -754,8 +764,10 @@ net::UploadElementReader* CefPostDataElementImpl::Get() {
}
void CefPostDataElementImpl::Set(const blink::WebHTTPBody::Element& element) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
{
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
}
if (element.type == blink::WebHTTPBody::Element::TypeData) {
SetToBytes(element.data.size(),
@ -768,7 +780,7 @@ void CefPostDataElementImpl::Set(const blink::WebHTTPBody::Element& element) {
}
void CefPostDataElementImpl::Get(blink::WebHTTPBody::Element& element) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (type_ == PDE_TYPE_BYTES) {
element.type = blink::WebHTTPBody::Element::TypeData;
@ -783,7 +795,7 @@ void CefPostDataElementImpl::Get(blink::WebHTTPBody::Element& element) {
}
void CefPostDataElementImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (read_only_ == read_only)
return;

View File

@ -7,6 +7,8 @@
#pragma once
#include "include/cef_request.h"
#include "base/synchronization/lock.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
namespace net {
@ -84,8 +86,9 @@ class CefRequestImpl : public CefRequest {
// True if this object is read-only.
bool read_only_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefRequestImpl);
IMPLEMENT_LOCKING(CefRequestImpl);
};
// Implementation of CefPostData
@ -116,8 +119,9 @@ class CefPostDataImpl : public CefPostData {
// True if this object is read-only.
bool read_only_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefPostDataImpl);
IMPLEMENT_LOCKING(CefPostDataImpl);
};
// Implementation of CefPostDataElement
@ -161,8 +165,9 @@ class CefPostDataElementImpl : public CefPostDataElement {
// True if this object is read-only.
bool read_only_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefPostDataElementImpl);
IMPLEMENT_LOCKING(CefPostDataElementImpl);
};
#endif // CEF_LIBCEF_COMMON_REQUEST_IMPL_H_

View File

@ -39,45 +39,45 @@ CefResponseImpl::CefResponseImpl()
}
bool CefResponseImpl::IsReadOnly() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return read_only_;
}
int CefResponseImpl::GetStatus() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return status_code_;
}
void CefResponseImpl::SetStatus(int status) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
status_code_ = status;
}
CefString CefResponseImpl::GetStatusText() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return status_text_;
}
void CefResponseImpl::SetStatusText(const CefString& statusText) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
status_text_ = statusText;
}
CefString CefResponseImpl::GetMimeType() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
return mime_type_;
}
void CefResponseImpl::SetMimeType(const CefString& mimeType) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
mime_type_ = mimeType;
}
CefString CefResponseImpl::GetHeader(const CefString& name) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CefString value;
@ -89,18 +89,18 @@ CefString CefResponseImpl::GetHeader(const CefString& name) {
}
void CefResponseImpl::GetHeaderMap(HeaderMap& map) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
map = header_map_;
}
void CefResponseImpl::SetHeaderMap(const HeaderMap& headerMap) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
header_map_ = headerMap;
}
net::HttpResponseHeaders* CefResponseImpl::GetResponseHeaders() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
std::string response;
std::string status_text;
@ -151,7 +151,7 @@ net::HttpResponseHeaders* CefResponseImpl::GetResponseHeaders() {
void CefResponseImpl::SetResponseHeaders(
const net::HttpResponseHeaders& headers) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
header_map_.empty();
@ -171,7 +171,7 @@ void CefResponseImpl::SetResponseHeaders(
void CefResponseImpl::Set(const blink::WebURLResponse& response) {
DCHECK(!response.isNull());
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
blink::WebString str;
@ -200,6 +200,6 @@ void CefResponseImpl::Set(const blink::WebURLResponse& response) {
}
void CefResponseImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
read_only_ = read_only;
}

View File

@ -8,6 +8,8 @@
#include "include/cef_response.h"
#include "base/synchronization/lock.h"
namespace net {
class HttpResponseHeaders;
}
@ -48,8 +50,9 @@ class CefResponseImpl : public CefResponse {
HeaderMap header_map_;
bool read_only_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefResponseImpl);
IMPLEMENT_LOCKING(CefResponseImpl);
};
#endif // CEF_LIBCEF_COMMON_RESPONSE_IMPL_H_

View File

@ -48,7 +48,7 @@ void CefSchemeRegistrarImpl::GetStandardSchemes(
}
bool CefSchemeRegistrarImpl::VerifyRefCount() {
return (GetRefCt() == 1);
return HasOneRef();
}
void CefSchemeRegistrarImpl::Detach() {

View File

@ -51,7 +51,7 @@ CefTrackManager::~CefTrackManager() {
}
void CefTrackManager::Add(CefTrackNode* object) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (!object->IsTracked()) {
tracker_.InsertTrackNext(object);
++object_count_;
@ -59,7 +59,7 @@ void CefTrackManager::Add(CefTrackNode* object) {
}
bool CefTrackManager::Delete(CefTrackNode* object) {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
if (object->IsTracked()) {
object->RemoveTracking();
delete object;
@ -70,7 +70,7 @@ bool CefTrackManager::Delete(CefTrackNode* object) {
}
void CefTrackManager::DeleteAll() {
AutoLock lock_scope(this);
base::AutoLock lock_scope(lock_);
CefTrackNode* next;
do {
next = tracker_.GetTrackNext();

View File

@ -8,6 +8,8 @@
#include "include/cef_base.h"
#include "base/synchronization/lock.h"
// Class extended by objects that must be tracked. After creating a tracked
// object you should add it to the appropriate track manager.
class CefTrackNode {
@ -67,8 +69,9 @@ class CefTrackManager : public CefBase {
CefTrackNode tracker_;
int object_count_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(CefTrackManager);
IMPLEMENT_LOCKING(CefTrackManager);
};
#endif // CEF_LIBCEF_COMMON_TRACKER_H_

View File

@ -241,7 +241,7 @@ void CefDOMDocumentImpl::Detach() {
// If you hit this assert it means that you are keeping references to this
// document object beyond the valid scope.
DCHECK_EQ(GetRefCt(), 1);
DCHECK(HasOneRef());
if (!node_map_.empty()) {
NodeMap::const_iterator it = node_map_.begin();

View File

@ -133,7 +133,7 @@ CefRefPtr<CefDOMNode> CefDOMEventImpl::GetCurrentTarget() {
void CefDOMEventImpl::Detach() {
// If you hit this assert it means that you are keeping references to this
// event object beyond the valid scope.
DCHECK_EQ(GetRefCt(), 1);
DCHECK(HasOneRef());
document_ = NULL;
event_.assign(WebDOMEvent());

View File

@ -31,7 +31,7 @@ class CefRenderURLRequest : public CefURLRequest {
scoped_refptr<Context> context_;
IMPLEMENT_REFCOUNTING(CefBrowserURLRequest);
IMPLEMENT_REFCOUNTING(CefRenderURLRequest);
};
#endif // CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_

View File

@ -0,0 +1,100 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This module gets enough CPU information to optimize the
// atomicops module on x86.
#include <stdint.h>
#include <string.h>
#include "include/base/cef_atomicops.h"
// This file only makes sense with atomicops_internals_x86_gcc.h -- it
// depends on structs that are defined in that file. If atomicops.h
// doesn't sub-include that file, then we aren't needed, and shouldn't
// try to do anything.
#ifdef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
// Inline cpuid instruction. In PIC compilations, %ebx contains the address
// of the global offset table. To avoid breaking such executables, this code
// must preserve that register's value across cpuid instructions.
#if defined(__i386__)
#define cpuid(a, b, c, d, inp) \
asm("mov %%ebx, %%edi\n" \
"cpuid\n" \
"xchg %%edi, %%ebx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
#elif defined(__x86_64__)
#define cpuid(a, b, c, d, inp) \
asm("mov %%rbx, %%rdi\n" \
"cpuid\n" \
"xchg %%rdi, %%rbx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
#endif
#if defined(cpuid) // initialize the struct only on x86
// Set the flags so that code will run correctly and conservatively, so even
// if we haven't been initialized yet, we're probably single threaded, and our
// default values should hopefully be pretty safe.
struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
false, // bug can't exist before process spawns multiple threads
};
namespace {
// Initialize the AtomicOps_Internalx86CPUFeatures struct.
void AtomicOps_Internalx86CPUFeaturesInit() {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
// Get vendor string (issue CPUID with eax = 0)
cpuid(eax, ebx, ecx, edx, 0);
char vendor[13];
memcpy(vendor, &ebx, 4);
memcpy(vendor + 4, &edx, 4);
memcpy(vendor + 8, &ecx, 4);
vendor[12] = 0;
// get feature flags in ecx/edx, and family/model in eax
cpuid(eax, ebx, ecx, edx, 1);
int family = (eax >> 8) & 0xf; // family and model fields
int model = (eax >> 4) & 0xf;
if (family == 0xf) { // use extended family and model fields
family += (eax >> 20) & 0xff;
model += ((eax >> 16) & 0xf) << 4;
}
// Opteron Rev E has a bug in which on very rare occasions a locked
// instruction doesn't act as a read-acquire barrier if followed by a
// non-locked read-modify-write instruction. Rev F has this bug in
// pre-release versions, but not in versions released to customers,
// so we test only for Rev E, which is family 15, model 32..63 inclusive.
if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD
family == 15 &&
32 <= model && model <= 63) {
AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
} else {
AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
}
}
class AtomicOpsx86Initializer {
public:
AtomicOpsx86Initializer() {
AtomicOps_Internalx86CPUFeaturesInit();
}
};
// A global to get use initialized on startup via static initialization :/
AtomicOpsx86Initializer g_initer;
} // namespace
#endif // if x86
#endif // ifdef CEF_INCLUDE_BASE_CEF_ATOMICOPS_INTERNALS_X86_GCC_H_

View File

@ -0,0 +1,14 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/cef_bind_helpers.h"
#include "include/base/cef_callback.h"
namespace base {
void DoNothing() {
}
} // namespace base

View File

@ -0,0 +1,42 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/cef_callback_helpers.h"
#include "include/base/cef_callback.h"
namespace base {
ScopedClosureRunner::ScopedClosureRunner() {
}
ScopedClosureRunner::ScopedClosureRunner(const Closure& closure)
: closure_(closure) {
}
ScopedClosureRunner::~ScopedClosureRunner() {
if (!closure_.is_null())
closure_.Run();
}
void ScopedClosureRunner::Reset() {
Closure old_closure = Release();
if (!old_closure.is_null())
old_closure.Run();
}
void ScopedClosureRunner::Reset(const Closure& closure) {
Closure old_closure = Release();
closure_ = closure;
if (!old_closure.is_null())
old_closure.Run();
}
Closure ScopedClosureRunner::Release() {
Closure result = closure_;
closure_.Reset();
return result;
}
} // namespace base

View File

@ -0,0 +1,38 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/internal/cef_callback_internal.h"
#include "include/base/cef_logging.h"
namespace base {
namespace internal {
bool CallbackBase::is_null() const {
return bind_state_.get() == NULL;
}
void CallbackBase::Reset() {
polymorphic_invoke_ = NULL;
// NULL the bind_state_ last, since it may be holding the last ref to whatever
// object owns us, and we may be deleted after that.
bind_state_ = NULL;
}
bool CallbackBase::Equals(const CallbackBase& other) const {
return bind_state_.get() == other.bind_state_.get() &&
polymorphic_invoke_ == other.polymorphic_invoke_;
}
CallbackBase::CallbackBase(BindStateBase* bind_state)
: bind_state_(bind_state),
polymorphic_invoke_(NULL) {
DCHECK(!bind_state_.get() || bind_state_->HasOneRef());
}
CallbackBase::~CallbackBase() {
}
} // namespace internal
} // namespace base

View File

@ -0,0 +1,44 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is used for debugging assertion support. The Lock class
// is functionally a wrapper around the LockImpl class, so the only
// real intelligence in the class is in the debugging logic.
#if !defined(NDEBUG)
#include "include/base/cef_lock.h"
#include "include/base/cef_logging.h"
namespace base {
Lock::Lock() : lock_() {
}
Lock::~Lock() {
DCHECK(owning_thread_ref_.is_null());
}
void Lock::AssertAcquired() const {
DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef());
}
void Lock::CheckHeldAndUnmark() {
DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef());
owning_thread_ref_ = PlatformThreadRef();
}
void Lock::CheckUnheldAndMark() {
// Hitting this DCHECK means that your code is trying to re-enter a lock that
// is already held. The Chromium Lock implementation is not reentrant.
// See "Why can the holder of a Lock not reacquire it?" at
// http://www.chromium.org/developers/lock-and-condition-variable for more
// information.
DCHECK(owning_thread_ref_.is_null());
owning_thread_ref_ = PlatformThread::CurrentRef();
}
} // namespace base
#endif // NDEBUG

View File

@ -0,0 +1,92 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/internal/cef_lock_impl.h"
#if defined(OS_WIN)
namespace base {
namespace internal {
LockImpl::LockImpl() {
// The second parameter is the spin count, for short-held locks it avoid the
// contending thread from going to sleep which helps performance greatly.
::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000);
}
LockImpl::~LockImpl() {
::DeleteCriticalSection(&native_handle_);
}
bool LockImpl::Try() {
if (::TryEnterCriticalSection(&native_handle_) != FALSE) {
return true;
}
return false;
}
void LockImpl::Lock() {
::EnterCriticalSection(&native_handle_);
}
void LockImpl::Unlock() {
::LeaveCriticalSection(&native_handle_);
}
} // namespace internal
} // namespace base
#elif defined(OS_POSIX)
#include <errno.h>
#include <string.h>
#include "include/base/cef_logging.h"
namespace base {
namespace internal {
LockImpl::LockImpl() {
#ifndef NDEBUG
// In debug, setup attributes for lock error checking.
pthread_mutexattr_t mta;
int rv = pthread_mutexattr_init(&mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
rv = pthread_mutex_init(&native_handle_, &mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
rv = pthread_mutexattr_destroy(&mta);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
#else
// In release, go with the default lock attributes.
pthread_mutex_init(&native_handle_, NULL);
#endif
}
LockImpl::~LockImpl() {
int rv = pthread_mutex_destroy(&native_handle_);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
bool LockImpl::Try() {
int rv = pthread_mutex_trylock(&native_handle_);
DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv);
return rv == 0;
}
void LockImpl::Lock() {
int rv = pthread_mutex_lock(&native_handle_);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
void LockImpl::Unlock() {
int rv = pthread_mutex_unlock(&native_handle_);
DCHECK_EQ(rv, 0) << ". " << strerror(rv);
}
} // namespace internal
} // namespace base
#endif // defined(OS_POSIX)

View File

@ -17,7 +17,8 @@
#include "include/internal/cef_string_types.h"
namespace cef_logging {
namespace cef {
namespace logging {
namespace {
@ -254,4 +255,5 @@ std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) {
return out;
}
} // namespace cef_logging
} // namespace logging
} // namespace cef

View File

@ -0,0 +1,53 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/cef_ref_counted.h"
#include "include/base/cef_thread_collision_warner.h"
namespace base {
namespace subtle {
bool RefCountedThreadSafeBase::HasOneRef() const {
return AtomicRefCountIsOne(
&const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
}
RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
#ifndef NDEBUG
in_dtor_ = false;
#endif
}
RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
#ifndef NDEBUG
DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
"calling Release()";
#endif
}
void RefCountedThreadSafeBase::AddRef() const {
#ifndef NDEBUG
DCHECK(!in_dtor_);
#endif
AtomicRefCountInc(&ref_count_);
}
bool RefCountedThreadSafeBase::Release() const {
#ifndef NDEBUG
DCHECK(!in_dtor_);
DCHECK(!AtomicRefCountIsZero(&ref_count_));
#endif
if (!AtomicRefCountDec(&ref_count_)) {
#ifndef NDEBUG
in_dtor_ = true;
#endif
return true;
}
return false;
}
} // namespace subtle
} // namespace base

View File

@ -0,0 +1,34 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/internal/cef_thread_checker_impl.h"
namespace base {
ThreadCheckerImpl::ThreadCheckerImpl()
: valid_thread_id_() {
EnsureThreadIdAssigned();
}
ThreadCheckerImpl::~ThreadCheckerImpl() {}
bool ThreadCheckerImpl::CalledOnValidThread() const {
EnsureThreadIdAssigned();
AutoLock auto_lock(lock_);
return valid_thread_id_ == PlatformThread::CurrentRef();
}
void ThreadCheckerImpl::DetachFromThread() {
AutoLock auto_lock(lock_);
valid_thread_id_ = PlatformThreadRef();
}
void ThreadCheckerImpl::EnsureThreadIdAssigned() const {
AutoLock auto_lock(lock_);
if (valid_thread_id_.is_null()) {
valid_thread_id_ = PlatformThread::CurrentRef();
}
}
} // namespace base

View File

@ -0,0 +1,65 @@
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/cef_thread_collision_warner.h"
#include "include/base/cef_logging.h"
#include "include/internal/cef_thread_internal.h"
namespace base {
void DCheckAsserter::warn() {
NOTREACHED() << "Thread Collision";
}
static subtle::Atomic32 CurrentThread() {
const cef_platform_thread_id_t current_thread_id =
cef_get_current_platform_thread_id();
// We need to get the thread id into an atomic data type. This might be a
// truncating conversion, but any loss-of-information just increases the
// chance of a fault negative, not a false positive.
const subtle::Atomic32 atomic_thread_id =
static_cast<subtle::Atomic32>(current_thread_id);
return atomic_thread_id;
}
void ThreadCollisionWarner::EnterSelf() {
// If the active thread is 0 then I'll write the current thread ID
// if two or more threads arrive here only one will succeed to
// write on valid_thread_id_ the current thread ID.
subtle::Atomic32 current_thread_id = CurrentThread();
int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
0,
current_thread_id);
if (previous_value != 0 && previous_value != current_thread_id) {
// gotcha! a thread is trying to use the same class and that is
// not current thread.
asserter_->warn();
}
subtle::NoBarrier_AtomicIncrement(&counter_, 1);
}
void ThreadCollisionWarner::Enter() {
subtle::Atomic32 current_thread_id = CurrentThread();
if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
0,
current_thread_id) != 0) {
// gotcha! another thread is trying to use the same class.
asserter_->warn();
}
subtle::NoBarrier_AtomicIncrement(&counter_, 1);
}
void ThreadCollisionWarner::Leave() {
if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
subtle::NoBarrier_Store(&valid_thread_id_, 0);
}
}
} // namespace base

View File

@ -0,0 +1,77 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/base/cef_weak_ptr.h"
namespace base {
namespace internal {
WeakReference::Flag::Flag() : is_valid_(true) {
// Flags only become bound when checked for validity, or invalidated,
// so that we can check that later validity/invalidation operations on
// the same Flag take place on the same thread.
thread_checker_.DetachFromThread();
}
void WeakReference::Flag::Invalidate() {
// The flag being invalidated with a single ref implies that there are no
// weak pointers in existence. Allow deletion on other thread in this case.
DCHECK(thread_checker_.CalledOnValidThread() || HasOneRef())
<< "WeakPtrs must be invalidated on the same thread.";
is_valid_ = false;
}
bool WeakReference::Flag::IsValid() const {
DCHECK(thread_checker_.CalledOnValidThread())
<< "WeakPtrs must be checked on the same thread.";
return is_valid_;
}
WeakReference::Flag::~Flag() {
}
WeakReference::WeakReference() {
}
WeakReference::WeakReference(const Flag* flag) : flag_(flag) {
}
WeakReference::~WeakReference() {
}
bool WeakReference::is_valid() const { return flag_.get() && flag_->IsValid(); }
WeakReferenceOwner::WeakReferenceOwner() {
}
WeakReferenceOwner::~WeakReferenceOwner() {
Invalidate();
}
WeakReference WeakReferenceOwner::GetRef() const {
// If we hold the last reference to the Flag then create a new one.
if (!HasRefs())
flag_ = new WeakReference::Flag();
return WeakReference(flag_.get());
}
void WeakReferenceOwner::Invalidate() {
if (flag_.get()) {
flag_->Invalidate();
flag_ = NULL;
}
}
WeakPtrBase::WeakPtrBase() {
}
WeakPtrBase::~WeakPtrBase() {
}
WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) {
}
} // namespace internal
} // namespace base

View File

@ -40,7 +40,7 @@ CefAllowCertificateErrorCallbackCppToC::CefAllowCertificateErrorCallbackCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefAllowCertificateErrorCallbackCppToC,
template<> base::AtomicRefCount CefCppToC<CefAllowCertificateErrorCallbackCppToC,
CefAllowCertificateErrorCallback,
cef_allow_certificate_error_callback_t>::DebugObjCt = 0;
#endif

View File

@ -119,6 +119,7 @@ CefAppCppToC::CefAppCppToC(CefApp* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefAppCppToC, CefApp, cef_app_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefAppCppToC, CefApp,
cef_app_t>::DebugObjCt = 0;
#endif

View File

@ -59,7 +59,7 @@ CefAuthCallbackCppToC::CefAuthCallbackCppToC(CefAuthCallback* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefAuthCallbackCppToC, CefAuthCallback,
cef_auth_callback_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefAuthCallbackCppToC,
CefAuthCallback, cef_auth_callback_t>::DebugObjCt = 0;
#endif

View File

@ -78,7 +78,7 @@ class CefBaseCppToC : public CefBase {
struct_.struct_.size = sizeof(cef_base_t);
struct_.struct_.add_ref = struct_add_ref;
struct_.struct_.release = struct_release;
struct_.struct_.get_refct = struct_get_refct;
struct_.struct_.has_one_ref = struct_has_one_ref;
}
virtual ~CefBaseCppToC() {}
@ -91,32 +91,33 @@ class CefBaseCppToC : public CefBase {
// CefBase methods increment/decrement reference counts on both this object
// and the underlying wrapper class.
int AddRef() {
void AddRef() const {
UnderlyingAddRef();
return refct_.AddRef();
ref_count_.AddRef();
}
int Release() {
bool Release() const {
UnderlyingRelease();
int retval = refct_.Release();
if (retval == 0)
if (ref_count_.Release()) {
delete this;
return retval;
return true;
}
return false;
}
int GetRefCt() { return refct_.GetRefCt(); }
bool HasOneRef() const { return ref_count_.HasOneRef(); }
// Increment/decrement reference counts on only the underlying class.
int UnderlyingAddRef() { return class_->AddRef(); }
int UnderlyingRelease() { return class_->Release(); }
int UnderlyingGetRefCt() { return class_->GetRefCt(); }
void UnderlyingAddRef() const { class_->AddRef(); }
bool UnderlyingRelease() const { return class_->Release(); }
bool UnderlyingHasOneRef() const { return class_->HasOneRef(); }
private:
static int CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) {
static void CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) {
DCHECK(base);
if (!base)
return 0;
return;
Struct* impl = reinterpret_cast<Struct*>(base);
return impl->class_->AddRef();
impl->class_->AddRef();
}
static int CEF_CALLBACK struct_release(struct _cef_base_t* base) {
@ -128,16 +129,16 @@ class CefBaseCppToC : public CefBase {
return impl->class_->Release();
}
static int CEF_CALLBACK struct_get_refct(struct _cef_base_t* base) {
static int CEF_CALLBACK struct_has_one_ref(struct _cef_base_t* base) {
DCHECK(base);
if (!base)
return 0;
Struct* impl = reinterpret_cast<Struct*>(base);
return impl->class_->GetRefCt();
return impl->class_->HasOneRef();
}
CefRefCount refct_;
CefRefCount ref_count_;
Struct struct_;
CefBase* class_;

View File

@ -42,7 +42,7 @@ CefBeforeDownloadCallbackCppToC::CefBeforeDownloadCallbackCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefBeforeDownloadCallbackCppToC,
template<> base::AtomicRefCount CefCppToC<CefBeforeDownloadCallbackCppToC,
CefBeforeDownloadCallback, cef_before_download_callback_t>::DebugObjCt =
0;
#endif

View File

@ -128,7 +128,7 @@ CefBinaryValueCppToC::CefBinaryValueCppToC(CefBinaryValue* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefBinaryValueCppToC, CefBinaryValue,
template<> base::AtomicRefCount CefCppToC<CefBinaryValueCppToC, CefBinaryValue,
cef_binary_value_t>::DebugObjCt = 0;
#endif

View File

@ -384,7 +384,7 @@ CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefBrowserCppToC, CefBrowser,
template<> base::AtomicRefCount CefCppToC<CefBrowserCppToC, CefBrowser,
cef_browser_t>::DebugObjCt = 0;
#endif

View File

@ -812,7 +812,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefBrowserHostCppToC, CefBrowserHost,
template<> base::AtomicRefCount CefCppToC<CefBrowserHostCppToC, CefBrowserHost,
cef_browser_host_t>::DebugObjCt = 0;
#endif

View File

@ -99,7 +99,7 @@ CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefBrowserProcessHandlerCppToC,
template<> base::AtomicRefCount CefCppToC<CefBrowserProcessHandlerCppToC,
CefBrowserProcessHandler, cef_browser_process_handler_t>::DebugObjCt = 0;
#endif

View File

@ -47,7 +47,7 @@ CefCallbackCppToC::CefCallbackCppToC(CefCallback* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefCallbackCppToC, CefCallback,
template<> base::AtomicRefCount CefCppToC<CefCallbackCppToC, CefCallback,
cef_callback_t>::DebugObjCt = 0;
#endif

View File

@ -288,7 +288,7 @@ CefClientCppToC::CefClientCppToC(CefClient* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefClientCppToC, CefClient,
template<> base::AtomicRefCount CefCppToC<CefClientCppToC, CefClient,
cef_client_t>::DebugObjCt = 0;
#endif

View File

@ -422,7 +422,7 @@ CefCommandLineCppToC::CefCommandLineCppToC(CefCommandLine* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefCommandLineCppToC, CefCommandLine,
template<> base::AtomicRefCount CefCppToC<CefCommandLineCppToC, CefCommandLine,
cef_command_line_t>::DebugObjCt = 0;
#endif

View File

@ -38,7 +38,7 @@ CefCompletionCallbackCppToC::CefCompletionCallbackCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefCompletionCallbackCppToC, CefCompletionCallback,
cef_completion_callback_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefCompletionCallbackCppToC,
CefCompletionCallback, cef_completion_callback_t>::DebugObjCt = 0;
#endif

View File

@ -126,7 +126,7 @@ CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefContextMenuHandlerCppToC, CefContextMenuHandler,
cef_context_menu_handler_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefContextMenuHandlerCppToC,
CefContextMenuHandler, cef_context_menu_handler_t>::DebugObjCt = 0;
#endif

View File

@ -273,7 +273,7 @@ CefContextMenuParamsCppToC::CefContextMenuParamsCppToC(
}
#ifndef NDEBUG
template<> long CefCppToC<CefContextMenuParamsCppToC, CefContextMenuParams,
cef_context_menu_params_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefContextMenuParamsCppToC,
CefContextMenuParams, cef_context_menu_params_t>::DebugObjCt = 0;
#endif

View File

@ -219,7 +219,7 @@ CefCookieManagerCppToC::CefCookieManagerCppToC(CefCookieManager* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefCookieManagerCppToC, CefCookieManager,
cef_cookie_manager_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefCookieManagerCppToC,
CefCookieManager, cef_cookie_manager_t>::DebugObjCt = 0;
#endif

View File

@ -64,7 +64,7 @@ CefCookieVisitorCppToC::CefCookieVisitorCppToC(CefCookieVisitor* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefCookieVisitorCppToC, CefCookieVisitor,
cef_cookie_visitor_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefCookieVisitorCppToC,
CefCookieVisitor, cef_cookie_visitor_t>::DebugObjCt = 0;
#endif

View File

@ -80,15 +80,15 @@ class CefCppToC : public CefBase {
struct_.struct_.base.size = sizeof(StructName);
struct_.struct_.base.add_ref = struct_add_ref;
struct_.struct_.base.release = struct_release;
struct_.struct_.base.get_refct = struct_get_refct;
struct_.struct_.base.has_one_ref = struct_has_one_ref;
#ifndef NDEBUG
CefAtomicIncrement(&DebugObjCt);
base::AtomicRefCountInc(&DebugObjCt);
#endif
}
virtual ~CefCppToC() {
#ifndef NDEBUG
CefAtomicDecrement(&DebugObjCt);
base::AtomicRefCountDec(&DebugObjCt);
#endif
}
@ -101,42 +101,42 @@ class CefCppToC : public CefBase {
// CefBase methods increment/decrement reference counts on both this object
// and the underlying wrapper class.
int AddRef() {
void AddRef() const {
UnderlyingAddRef();
return refct_.AddRef();
ref_count_.AddRef();
}
int Release() {
bool Release() const {
UnderlyingRelease();
int retval = refct_.Release();
if (retval == 0)
if (ref_count_.Release()) {
delete this;
return retval;
return true;
}
return false;
}
int GetRefCt() { return refct_.GetRefCt(); }
bool HasOneRef() const { return ref_count_.HasOneRef(); }
// Increment/decrement reference counts on only the underlying class.
int UnderlyingAddRef() { return class_->AddRef(); }
int UnderlyingRelease() { return class_->Release(); }
int UnderlyingGetRefCt() { return class_->GetRefCt(); }
void UnderlyingAddRef() const { class_->AddRef(); }
bool UnderlyingRelease() const { return class_->Release(); }
bool UnderlyingHasOneRef() const { return class_->HasOneRef(); }
#ifndef NDEBUG
// Simple tracking of allocated objects.
static long DebugObjCt; // NOLINT(runtime/int)
static base::AtomicRefCount DebugObjCt; // NOLINT(runtime/int)
#endif
protected:
CefRefCount refct_;
Struct struct_;
BaseName* class_;
private:
static int CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) {
static void CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) {
DCHECK(base);
if (!base)
return 0;
return;
Struct* impl = reinterpret_cast<Struct*>(base);
return impl->class_->AddRef();
impl->class_->AddRef();
}
static int CEF_CALLBACK struct_release(struct _cef_base_t* base) {
@ -148,15 +148,17 @@ class CefCppToC : public CefBase {
return impl->class_->Release();
}
static int CEF_CALLBACK struct_get_refct(struct _cef_base_t* base) {
static int CEF_CALLBACK struct_has_one_ref(struct _cef_base_t* base) {
DCHECK(base);
if (!base)
return 0;
Struct* impl = reinterpret_cast<Struct*>(base);
return impl->class_->GetRefCt();
return impl->class_->HasOneRef();
}
CefRefCount ref_count_;
DISALLOW_COPY_AND_ASSIGN(CefCppToC);
};

View File

@ -65,7 +65,7 @@ CefDialogHandlerCppToC::CefDialogHandlerCppToC(CefDialogHandler* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefDialogHandlerCppToC, CefDialogHandler,
cef_dialog_handler_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefDialogHandlerCppToC,
CefDialogHandler, cef_dialog_handler_t>::DebugObjCt = 0;
#endif

View File

@ -571,7 +571,7 @@ CefDictionaryValueCppToC::CefDictionaryValueCppToC(CefDictionaryValue* cls)
}
#ifndef NDEBUG
template<> long CefCppToC<CefDictionaryValueCppToC, CefDictionaryValue,
cef_dictionary_value_t>::DebugObjCt = 0;
template<> base::AtomicRefCount CefCppToC<CefDictionaryValueCppToC,
CefDictionaryValue, cef_dictionary_value_t>::DebugObjCt = 0;
#endif

Some files were not shown because too many files have changed in this diff Show More