diff --git a/cef_paths2.gypi b/cef_paths2.gypi index e232631e8..40a4ab427 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -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', diff --git a/include/base/cef_atomic_ref_count.h b/include/base/cef_atomic_ref_count.h new file mode 100644 index 000000000..cd9b648be --- /dev/null +++ b/include/base/cef_atomic_ref_count.h @@ -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_ diff --git a/include/base/cef_atomicops.h b/include/base/cef_atomicops.h new file mode 100644 index 000000000..cd83115c0 --- /dev/null +++ b/include/base/cef_atomicops.h @@ -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 + +#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_ diff --git a/include/base/cef_basictypes.h b/include/base/cef_basictypes.h new file mode 100644 index 000000000..af3431127 --- /dev/null +++ b/include/base/cef_basictypes.h @@ -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 // For UINT_MAX +#include // 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 +// 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_ diff --git a/include/base/cef_bind.h b/include/base/cef_bind.h new file mode 100644 index 000000000..c3f56f337 --- /dev/null +++ b/include/base/cef_bind.h @@ -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 +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void()> + ::UnboundRunType> +Bind(Functor functor) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + typedef internal::BindState BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor))); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + typedef internal::BindState::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::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::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::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::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::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::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::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::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p6_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::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::RunnableType RunnableType; + typedef typename internal::FunctorTraits::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 + 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::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::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::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p6_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p7_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + 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_ diff --git a/include/base/cef_bind_helpers.h b/include/base/cef_bind_helpers.h new file mode 100644 index 000000000..8edac5c03 --- /dev/null +++ b/include/base/cef_bind_helpers.h @@ -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 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 arg) { } +// scoped_ptr CreateFoo() { return scoped_ptr(new Foo()); } +// +// scoped_ptr 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() - 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 +// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); +// +// template +// No NotTheCheckWeWant(...); +// +// static const bool value = sizeof(NotTheCheckWeWant(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 +// No GoodCheck(Helper<&C::TargetFunc>*); +// +// template +// Yes GoodCheck(...); +// +// static const bool value = sizeof(GoodCheck(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(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 +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 struct Helper {}; + + template + static No& Check(Helper<&C::AddRef>*); + + template + static Yes& Check(...); + + public: + static const bool value = sizeof(Check(0)) == sizeof(Yes); +}; + +// Helpers to assert that arguments of a recounted type are bound with a +// scoped_refptr. +template +struct UnsafeBindtoRefCountedArgHelper : false_type { +}; + +template +struct UnsafeBindtoRefCountedArgHelper + : integral_constant::value> { +}; + +template +struct UnsafeBindtoRefCountedArg : false_type { +}; + +template +struct UnsafeBindtoRefCountedArg + : UnsafeBindtoRefCountedArgHelper::value, T> { +}; + +template +class HasIsMethodTag { + typedef char Yes[1]; + typedef char No[2]; + + template + static Yes& Check(typename U::IsMethod*); + + template + static No& Check(...); + + public: + static const bool value = sizeof(Check(0)) == sizeof(Yes); +}; + +template +class UnretainedWrapper { + public: + explicit UnretainedWrapper(T* o) : ptr_(o) {} + T* get() const { return ptr_; } + private: + T* ptr_; +}; + +template +class ConstRefWrapper { + public: + explicit ConstRefWrapper(const T& o) : ptr_(&o) {} + const T& get() const { return *ptr_; } + private: + const T* ptr_; +}; + +template +struct IgnoreResultHelper { + explicit IgnoreResultHelper(T functor) : functor_(functor) {} + + T functor_; +}; + +template +struct IgnoreResultHelper > { + explicit IgnoreResultHelper(const Callback& functor) : functor_(functor) {} + + const Callback& 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 +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 +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 +struct UnwrapTraits { + typedef const T& ForwardType; + static ForwardType Unwrap(const T& o) { return o; } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(UnretainedWrapper unretained) { + return unretained.get(); + } +}; + +template +struct UnwrapTraits > { + typedef const T& ForwardType; + static ForwardType Unwrap(ConstRefWrapper const_ref) { + return const_ref.get(); + } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(const scoped_refptr& o) { return o.get(); } +}; + +template +struct UnwrapTraits > { + typedef const WeakPtr& ForwardType; + static ForwardType Unwrap(const WeakPtr& o) { return o; } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(const OwnedWrapper& o) { + return o.get(); + } +}; + +template +struct UnwrapTraits > { + typedef T ForwardType; + static T Unwrap(PassedWrapper& o) { + return o.Pass(); + } +}; + +// Utility for handling different refcounting semantics in the Bind() +// function. +template +struct MaybeRefcount; + +template +struct MaybeRefcount { + static void AddRef(const T&) {} + static void Release(const T&) {} +}; + +template +struct MaybeRefcount { + static void AddRef(const T*) {} + static void Release(const T*) {} +}; + +template +struct MaybeRefcount { + static void AddRef(const T&) {} + static void Release(const T&) {} +}; + +template +struct MaybeRefcount { + 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 +struct MaybeRefcount > { + static void AddRef(const scoped_refptr& o) {} + static void Release(const scoped_refptr& o) {} +}; + +template +struct MaybeRefcount { + 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 +struct IsWeakMethod : public false_type {}; + +template +struct IsWeakMethod > : public true_type {}; + +template +struct IsWeakMethod > > : public true_type {}; + +} // namespace internal + +template +static inline internal::UnretainedWrapper Unretained(T* o) { + return internal::UnretainedWrapper(o); +} + +template +static inline internal::ConstRefWrapper ConstRef(const T& o) { + return internal::ConstRefWrapper(o); +} + +template +static inline internal::OwnedWrapper Owned(T* o) { + return internal::OwnedWrapper(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 +static inline internal::PassedWrapper Passed(T scoper) { + return internal::PassedWrapper(scoper.Pass()); +} +template +static inline internal::PassedWrapper Passed(T* scoper) { + return internal::PassedWrapper(scoper->Pass()); +} + +template +static inline internal::IgnoreResultHelper IgnoreResult(T data) { + return internal::IgnoreResultHelper(data); +} + +template +static inline internal::IgnoreResultHelper > +IgnoreResult(const Callback& data) { + return internal::IgnoreResultHelper >(data); +} + +void DoNothing(); + +template +void DeletePointer(T* obj) { + delete obj; +} + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ diff --git a/include/base/cef_build.h b/include/base/cef_build.h index 934976a75..10b1bdecc 100644 --- a/include/base/cef_build.h +++ b/include/base/cef_build.h @@ -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 . +#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_ diff --git a/include/base/cef_callback.h b/include/base/cef_callback.h new file mode 100644 index 000000000..002f78fbf --- /dev/null +++ b/include/base/cef_callback.h @@ -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) +// 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 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 { +// public: +// int Foo() { return 3; } +// void PrintBye() { LOG(INFO) << "bye."; } +// }; +// scoped_refptr ref = new Ref(); +// base::Callback 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& 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& 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 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 cb = base::Bind(&MyFunc, 23, "hello world"); +// cb.Run(); +// +// A callback with no unbound input parameters (base::Callback) +// 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 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) 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 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 arg) {} +// scoped_ptr 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 arg) {} +// scoped_refptr 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 is convertible to tr1::function). +// +// 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 +class Callback; + +namespace internal { +template +struct BindState; +} // namespace internal + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run() const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get()); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3) const { + PolymorphicInvoke f = + reinterpret_cast(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::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4) const { + PolymorphicInvoke f = + reinterpret_cast(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::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5) const { + PolymorphicInvoke f = + reinterpret_cast(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::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6) const { + PolymorphicInvoke f = + reinterpret_cast(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::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : 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 + Callback(internal::BindState* 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 + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6, + typename internal::CallbackParamTraits::ForwardType a7) const { + PolymorphicInvoke f = + reinterpret_cast(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::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + + +// Syntactic sugar to make Callbacks easier to declare since it +// will be used in a lot of APIs with delayed execution. +typedef Callback Closure; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_H_ diff --git a/include/base/cef_callback_forward.h b/include/base/cef_callback_forward.h new file mode 100644 index 000000000..4986b8f76 --- /dev/null +++ b/include/base/cef_callback_forward.h @@ -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 +class Callback; + +typedef Callback Closure; + +} // namespace base + +#endif // !!BUILDING_CEF_SHARED + +#endif // INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ diff --git a/include/base/cef_callback_helpers.h b/include/base/cef_callback_helpers.h new file mode 100644 index 000000000..62a0c8752 --- /dev/null +++ b/include/base/cef_callback_helpers.h @@ -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 +base::Callback ResetAndReturn(base::Callback* cb) { + base::Callback 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_ diff --git a/include/base/cef_callback_list.h b/include/base/cef_callback_list.h new file mode 100644 index 000000000..e198fd390 --- /dev/null +++ b/include/base/cef_callback_list.h @@ -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 + +#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 OnFooCallback; +// +// scoped_ptr::Subscription> +// RegisterCallback(const OnFooCallback& cb) { +// return callback_list_.Add(cb); +// } +// +// private: +// void NotifyFoo(const Foo& foo) { +// callback_list_.Notify(foo); +// } +// +// base::CallbackList 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::Subscription> +// foo_subscription_; +// +// DISALLOW_COPY_AND_ASSIGN(MyWidgetListener); +// }; + +namespace base { + +namespace internal { + +template +class CallbackListBase { + public: + class Subscription { + public: + Subscription(CallbackListBase* list, + typename std::list::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* list_; + typename std::list::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 Add(const CallbackType& cb) WARN_UNUSED_RESULT { + DCHECK(!cb.is_null()); + return scoped_ptr( + 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* 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* list_; + typename std::list::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::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 callbacks_; + int active_iterator_count_; + Closure removal_callback_; + + DISALLOW_COPY_AND_ASSIGN(CallbackListBase); +}; + +} // namespace internal + +template class CallbackList; + +template <> +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify() { + internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5) { + typename internal::CallbackListBase::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 +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6) { + typename internal::CallbackListBase::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 +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6, + typename internal::CallbackParamTraits::ForwardType a7) { + typename internal::CallbackListBase::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_ diff --git a/include/base/cef_cancelable_callback.h b/include/base/cef_cancelable_callback.h new file mode 100644 index 000000000..8ad3bf3bb --- /dev/null +++ b/include/base/cef_cancelable_callback.h @@ -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 +class CancelableCallback; + +template <> +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& 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& 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& 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::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +template +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& 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& 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& 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::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +template +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& 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& 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& 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::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +typedef CancelableCallback CancelableClosure; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ diff --git a/include/base/cef_lock.h b/include/base/cef_lock.h new file mode 100644 index 000000000..d50d60ba8 --- /dev/null +++ b/include/base/cef_lock.h @@ -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_ diff --git a/include/base/cef_logging.h b/include/base/cef_logging.h index 677414975..b3951f12e 100644 --- a/include/base/cef_logging.h +++ b/include/base/cef_logging.h @@ -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 diff --git a/include/base/cef_macros.h b/include/base/cef_macros.h index 0c874ffe1..41b40e79a 100644 --- a/include/base/cef_macros.h +++ b/include/base/cef_macros.h @@ -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 +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 +// +// 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_ diff --git a/include/base/cef_move.h b/include/base/cef_move.h new file mode 100644 index 000000000..91069297d --- /dev/null +++ b/include/base/cef_move.h @@ -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 +// 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(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 p)" accept a +// value of type scoped_ptr 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& 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_ diff --git a/include/base/cef_platform_thread.h b/include/base/cef_platform_thread.h new file mode 100644 index 000000000..cda1dc45b --- /dev/null +++ b/include/base/cef_platform_thread.h @@ -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_ diff --git a/include/base/cef_ref_counted.h b/include/base/cef_ref_counted.h new file mode 100644 index 000000000..55d41e1b4 --- /dev/null +++ b/include/base/cef_ref_counted.h @@ -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 + +#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 class. To use this guy just extend your +// class from it like so: +// +// class MyFoo : public base::RefCounted { +// ... +// private: +// friend class base::RefCounted; +// ~MyFoo(); +// }; +// +// You should always make your destructor private, to avoid any code deleting +// the object accidently while there are references to it. +template +class RefCounted : public subtle::RefCountedBase { + public: + RefCounted() {} + + void AddRef() const { + subtle::RefCountedBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedBase::Release()) { + delete static_cast(this); + } + } + + protected: + ~RefCounted() {} + + private: + DISALLOW_COPY_AND_ASSIGN(RefCounted); +}; + +// Forward declaration. +template class RefCountedThreadSafe; + +// Default traits for RefCountedThreadSafe. Deletes the object when its ref +// count reaches 0. Overload to delete it on a different thread etc. +template +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::DeleteInternal(x); + } +}; + +// +// A thread-safe variant of RefCounted +// +// class MyFoo : public base::RefCountedThreadSafe { +// ... +// }; +// +// 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(); +template > +class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { + public: + RefCountedThreadSafe() {} + + void AddRef() const { + subtle::RefCountedThreadSafeBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedThreadSafeBase::Release()) { + Traits::Destruct(static_cast(this)); + } + } + + protected: + ~RefCountedThreadSafe() {} + + private: + friend struct DefaultRefCountedThreadSafeTraits; + 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 +class RefCountedData + : public base::RefCountedThreadSafe< base::RefCountedData > { + public: + RefCountedData() : data() {} + RefCountedData(const T& in_value) : data(in_value) {} + + T data; + + private: + friend class base::RefCountedThreadSafe >; + ~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 { +// ... +// }; +// +// void some_function() { +// scoped_refptr foo = new MyFoo(); +// foo->Method(param); +// // |foo| is released when this function returns +// } +// +// void some_other_function() { +// scoped_refptr foo = new MyFoo(); +// ... +// foo = NULL; // explicitly releases |foo| +// ... +// if (foo) +// foo->Method(param); +// } +// +// The above examples show how scoped_refptr acts like a pointer to T. +// Given two scoped_refptr classes, it is also possible to exchange +// references between the two objects, like so: +// +// { +// scoped_refptr a = new MyFoo(); +// scoped_refptr 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 a = new MyFoo(); +// scoped_refptr b; +// +// b = a; +// // now, |a| and |b| each own a reference to the same MyFoo object. +// } +// +template +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& r) : ptr_(r.ptr_) { + if (ptr_) + ptr_->AddRef(); + } + + template + scoped_refptr(const scoped_refptr& r) : ptr_(r.get()) { + if (ptr_) + ptr_->AddRef(); + } + + ~scoped_refptr() { + if (ptr_) + ptr_->Release(); + } + + T* get() const { return ptr_; } + + // Allow scoped_refptr to be used in boolean expression + // and comparison operations. + operator T*() const { return ptr_; } + + T* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + + scoped_refptr& 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& operator=(const scoped_refptr& r) { + return *this = r.ptr_; + } + + template + scoped_refptr& operator=(const scoped_refptr& r) { + return *this = r.get(); + } + + void swap(T** pp) { + T* p = ptr_; + ptr_ = *pp; + *pp = p; + } + + void swap(scoped_refptr& r) { + swap(&r.ptr_); + } + + protected: + T* ptr_; +}; + +// Handy utility for creating a scoped_refptr out of a T* explicitly without +// having to retype all the template arguments +template +scoped_refptr make_scoped_refptr(T* t) { + return scoped_refptr(t); +} + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_ diff --git a/include/base/cef_scoped_ptr.h b/include/base/cef_scoped_ptr.h new file mode 100644 index 000000000..be9b2007a --- /dev/null +++ b/include/base/cef_scoped_ptr.h @@ -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): +// { +// scoped_ptr foo(new Foo("wee")); +// } // foo goes out of scope, releasing the pointer with it. +// +// { +// scoped_ptr 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): +// { +// scoped_ptr 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 arg) { +// // Do something with arg +// } +// scoped_ptr CreateFoo() { +// // No need for calling Pass() because we are constructing a temporary +// // for the return value. +// return scoped_ptr(new Foo("new")); +// } +// scoped_ptr PassThru(scoped_ptr arg) { +// return arg.Pass(); +// } +// +// { +// scoped_ptr ptr(new Foo("yay")); // ptr manages Foo("yay"). +// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). +// scoped_ptr ptr2 = CreateFoo(); // ptr2 owns the return Foo. +// scoped_ptr 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 to initialize a scoped_ptr: +// +// scoped_ptr foo(new Foo()); +// scoped_ptr parent(foo.Pass()); +// +// PassAs<>() should be used to upcast return value in return statement: +// +// scoped_ptr CreateFoo() { +// scoped_ptr result(new FooChild()); +// return result.PassAs(); +// } +// +// Note that PassAs<>() is implemented only for scoped_ptr, but not for +// scoped_ptr. 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 +#include +#include + +#include // 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. +template +struct DefaultDeleter { + DefaultDeleter() {} + template DefaultDeleter(const DefaultDeleter& 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 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::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 +struct DefaultDeleter { + 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 void operator()(U* array) const; +}; + +template +struct DefaultDeleter { + // Never allow someone to declare something like scoped_ptr. + 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 foo_ptr( +// static_cast(malloc(sizeof(int)))); +struct FreeDeleter { + inline void operator()(void* ptr) const { + free(ptr); + } +}; + +namespace internal { + +template struct IsNotRefCounted { + enum { + value = !base::is_convertible::value && + !base::is_convertible:: + value + }; +}; + +// Minimal implementation of the core logic of scoped_ptr, suitable for +// reuse in both scoped_ptr and its specializations. +template +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 + scoped_ptr_impl(scoped_ptr_impl* 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 + void TakeState(scoped_ptr_impl* 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(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(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(data_), static_cast(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 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 is like a T*, except that the destructor of scoped_ptr +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr owns the T object that it points to. +// Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. +// Also like T*, scoped_ptr 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) == 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 scoped_ptr { + MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + + COMPILE_ASSERT(base::internal::IsNotRefCounted::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 + scoped_ptr(scoped_ptr other) : impl_(&other.impl_) { + COMPILE_ASSERT(!base::is_array::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 + scoped_ptr& operator=(scoped_ptr rhs) { + COMPILE_ASSERT(!base::is_array::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 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 + 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 + scoped_ptr PassAs() { + return scoped_ptr(Pass()); + } + + private: + // Needed to reach into |impl_| in the constructor. + template friend class scoped_ptr; + base::internal::scoped_ptr_impl 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 bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; +}; + +template +class scoped_ptr { + 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(). + // However, because of the first bullet in this comment, users MUST + // NOT use implicit_cast() 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 to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + private: + typedef base::internal::scoped_ptr_impl + 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 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 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 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 bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; +}; + +// Free functions +template +void swap(scoped_ptr& p1, scoped_ptr& p2) { + p1.swap(p2); +} + +template +bool operator==(T* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +bool operator!=(T* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +// A function to convert T* into scoped_ptr +// Doing e.g. make_scoped_ptr(new FooBarBaz(arg)) is a shorter notation +// for scoped_ptr >(new FooBarBaz(arg)) +template +scoped_ptr make_scoped_ptr(T* ptr) { + return scoped_ptr(ptr); +} + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_ diff --git a/include/base/cef_template_util.h b/include/base/cef_template_util.h new file mode 100644 index 000000000..dc82548a5 --- /dev/null +++ b/include/base/cef_template_util.h @@ -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 // For size_t. + +#include "include/base/cef_build.h" + +namespace base { + +// template definitions from tr1 + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template struct is_pointer : false_type {}; +template struct is_pointer : 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 +struct is_member_function_pointer : false_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + + +template struct is_same : public false_type {}; +template struct is_same : true_type {}; + +template struct is_array : public false_type {}; +template struct is_array : public true_type {}; +template struct is_array : public true_type {}; + +template struct is_non_const_reference : false_type {}; +template struct is_non_const_reference : true_type {}; +template struct is_non_const_reference : false_type {}; + +template struct is_const : false_type {}; +template struct is_const : true_type {}; + +template struct is_void : false_type {}; +template <> struct is_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 + static YesType Test(To); + + template + static NoType Test(...); + + template + 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 + static YesType Test(void(C::*)(void)); + + template + 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 +struct is_convertible + : integral_constant( + internal::ConvertHelper::Create())) == + sizeof(internal::YesType)> { +}; + +template +struct is_class + : integral_constant(0)) == + sizeof(internal::YesType)> { +}; + +template +struct enable_if {}; + +template +struct enable_if { typedef T type; }; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_ diff --git a/include/base/cef_thread_checker.h b/include/base/cef_thread_checker.h new file mode 100644 index 000000000..2fd4f271a --- /dev/null +++ b/include/base/cef_thread_checker.h @@ -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_ diff --git a/include/base/cef_thread_collision_warner.h b/include/base/cef_thread_collision_warner.h new file mode 100644 index 000000000..bbc88759c --- /dev/null +++ b/include/base/cef_thread_collision_warner.h @@ -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 + +#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_ diff --git a/include/internal/cef_tuple.h b/include/base/cef_tuple.h similarity index 68% rename from include/internal/cef_tuple.h rename to include/base/cef_tuple.h index c2cdf7058..b33eae9b0 100644 --- a/include/internal/cef_tuple.h +++ b/include/base/cef_tuple.h @@ -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::ParamType a, typename TupleTraits::ParamType b, typename TupleTraits::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 inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { - (obj->*method)(arg); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& 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::Unwrap(arg.a)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple2& arg) { - (obj->*method)(arg.a, arg.b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple3& arg) { - (obj->*method)(arg.a, arg.b, arg.c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple4& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple5& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple6& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple7& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple8& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g), + base::internal::UnwrapTraits::Unwrap(arg.h)); } // Static Dispatchers with no out params. @@ -641,49 +676,77 @@ inline void DispatchToFunction(Function function, const A& arg) { template inline void DispatchToFunction(Function function, const Tuple1& arg) { - (*function)(arg.a); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a)); } template inline void DispatchToFunction(Function function, const Tuple2& arg) { - (*function)(arg.a, arg.b); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); } template inline void DispatchToFunction(Function function, const Tuple3& arg) { - (*function)(arg.a, arg.b, arg.c); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); } template inline void DispatchToFunction(Function function, const Tuple4& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); } template inline void DispatchToFunction(Function function, const Tuple5& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); } template inline void DispatchToFunction(Function function, const Tuple6& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); } template inline void DispatchToFunction(Function function, const Tuple7& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g)); } template inline void DispatchToFunction(Function function, const Tuple8& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h); + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g), + base::internal::UnwrapTraits::Unwrap(arg.h)); } // Dispatchers with 0 out param (as a Tuple0). @@ -697,46 +760,61 @@ inline void DispatchToMethod(ObjT* obj, template inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) { - (obj->*method)(arg); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& arg, Tuple0*) { - (obj->*method)(arg.a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple2& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple3& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple4& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple5& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); } template inline void DispatchToMethod(ObjT* obj, Method method, const Tuple6& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); } // Dispatchers with 1 out param. @@ -762,7 +840,7 @@ template& in, Tuple1* out) { - (obj->*method)(in.a, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), &out->a); } template& in, Tuple1* out) { - (obj->*method)(in.a, in.b, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a); } template& in, Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a); } template& in, Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a); } template& in, Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a); } template& in, Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a); } // Dispatchers with 2 out params. @@ -829,7 +927,8 @@ template& in, Tuple2* out) { - (obj->*method)(in.a, &out->a, &out->b); + (obj->*method)( + base::internal::UnwrapTraits::Unwrap(in.a), &out->a, &out->b); } template& in, Tuple2* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b); } template& in, Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b); } template& in, Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b); } template& in, Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b); } template& in, Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b); } // Dispatchers with 3 out params. @@ -897,7 +1021,10 @@ template& in, Tuple3* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c); } template& in, Tuple3* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c); } template& in, Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c); } template& in, Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c); } template& in, Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b, &out->c); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c); } template& in, Tuple3* 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::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b, + &out->c); } // Dispatchers with 4 out params. @@ -957,7 +1114,11 @@ template* out) { - (obj->*method)(in, &out->a, &out->b, &out->c, &out->d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* 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::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c, + &out->d); } template& in, Tuple4* 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::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b, + &out->c, + &out->d); } // Dispatchers with 5 out params. @@ -1027,7 +1225,12 @@ template* out) { - (obj->*method)(in, &out->a, &out->b, &out->c, &out->d, &out->e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); } template& in, Tuple5* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d, &out->e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); } template& in, Tuple5* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d, &out->e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); } template& in, Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d, &out->e); + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); } template& in, Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d, + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c, + &out->d, &out->e); } @@ -1069,8 +1297,16 @@ template& in, Tuple5* 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::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); } template& in, Tuple5* 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::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::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_ diff --git a/include/base/cef_weak_ptr.h b/include/base/cef_weak_ptr.h new file mode 100644 index 000000000..6d8e2dbe7 --- /dev/null +++ b/include/base/cef_weak_ptr.h @@ -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 weak_factory_; +// }; +// +// class Worker { +// public: +// static void StartNew(const WeakPtr& controller) { +// Worker* worker = new Worker(controller); +// // Kick off asynchronous processing... +// } +// private: +// Worker(const WeakPtr& controller) +// : controller_(controller) {} +// void DidCompleteAsynchronousProcessing(const Result& result) { +// if (controller_) +// controller_->WorkComplete(result); +// } +// WeakPtr 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 class SupportsWeakPtr; +template 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 { + public: + Flag(); + + void Invalidate(); + bool IsValid() const; + + private: + friend class base::RefCountedThreadSafe; + + ~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 flag_; +}; + +class WeakReferenceOwner { + public: + WeakReferenceOwner(); + ~WeakReferenceOwner(); + + WeakReference GetRef() const; + + bool HasRefs() const { + return flag_.get() && !flag_->HasOneRef(); + } + + void Invalidate(); + + private: + mutable scoped_refptr flag_; +}; + +// This class simplifies the implementation of WeakPtr's type conversion +// constructor by avoiding the need for a public accessor for ref_. A +// WeakPtr cannot access the private members of WeakPtr, 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 to WeakPtr. This + // conversion will only compile if there is exists a Base which inherits + // from SupportsWeakPtr. See base::AsWeakPtr() below for a helper + // function that makes calling this easier. + template + static WeakPtr StaticAsWeakPtr(Derived* t) { + typedef + is_convertible convertible; + COMPILE_ASSERT(convertible::value, + AsWeakPtr_argument_inherits_from_SupportsWeakPtr); + return AsWeakPtrImpl(t, *t); + } + + private: + // This template function uses type inference to find a Base of Derived + // which is an instance of SupportsWeakPtr. We can then safely + // static_cast the Base* to a Derived*. + template + static WeakPtr AsWeakPtrImpl( + Derived* t, const SupportsWeakPtr&) { + WeakPtr ptr = t->Base::AsWeakPtr(); + return WeakPtr(ptr.ref_, static_cast(ptr.ptr_)); + } +}; + +} // namespace internal + +template 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; +// if (foo) +// foo->method(); +// +template +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 + WeakPtr(const WeakPtr& 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 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 bool operator==(WeakPtr const&) const; + template bool operator!=(WeakPtr const&) const; + + friend class internal::SupportsWeakPtrBase; + template friend class WeakPtr; + friend class SupportsWeakPtr; + friend class WeakPtrFactory; + + 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 that is used to pass around a weak reference to a bool. +template +class WeakPtrFactory { + public: + explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { + } + + ~WeakPtrFactory() { + ptr_ = NULL; + } + + WeakPtr GetWeakPtr() { + DCHECK(ptr_); + return WeakPtr(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 SupportsWeakPtr : public internal::SupportsWeakPtrBase { + public: + SupportsWeakPtr() {} + + WeakPtr AsWeakPtr() { + return WeakPtr(weak_reference_owner_.GetRef(), static_cast(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 +// when Derived doesn't directly extend SupportsWeakPtr, instead it +// extends a Base that extends SupportsWeakPtr. +// +// EXAMPLE: +// class Base : public base::SupportsWeakPtr {}; +// class Derived : public Base {}; +// +// Derived derived; +// base::WeakPtr ptr = base::AsWeakPtr(&derived); +// +// Note that the following doesn't work (invalid type conversion) since +// Derived::AsWeakPtr() is WeakPtr SupportsWeakPtr::AsWeakPtr(), +// and there's no way to safely cast WeakPtr to WeakPtr at +// the caller. +// +// base::WeakPtr ptr = derived.AsWeakPtr(); // Fails. + +template +WeakPtr AsWeakPtr(Derived* t) { + return internal::SupportsWeakPtrBase::StaticAsWeakPtr(t); +} + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_ diff --git a/include/base/internal/cef_atomicops_atomicword_compat.h b/include/base/internal/cef_atomicops_atomicword_compat.h new file mode 100644 index 000000000..985f0f9b9 --- /dev/null +++ b/include/base/internal/cef_atomicops_atomicword_compat.h @@ -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(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Acquire_CompareAndSwap( + reinterpret_cast(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(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store( + reinterpret_cast(ptr), value); +} + +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Acquire_Store( + reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Release_Store( + reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return base::subtle::Acquire_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { + return base::subtle::Release_Load( + reinterpret_cast(ptr)); +} + +} // namespace base::subtle +} // namespace base + +#endif // !defined(ARCH_CPU_64_BITS) + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_ diff --git a/include/base/internal/cef_atomicops_mac.h b/include/base/internal/cef_atomicops_mac.h new file mode 100644 index 000000000..9f268dd67 --- /dev/null +++ b/include/base/internal/cef_atomicops_mac.h @@ -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 + +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(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(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32(increment, const_cast(ptr)); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32Barrier(increment, const_cast(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(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(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(ptr))); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64(increment, reinterpret_cast(ptr)); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64Barrier(increment, + reinterpret_cast(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(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_ diff --git a/include/base/internal/cef_atomicops_x86_gcc.h b/include/base/internal/cef_atomicops_x86_gcc.h new file mode 100644 index 000000000..0e2139d95 --- /dev/null +++ b/include/base/internal/cef_atomicops_x86_gcc.h @@ -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_ diff --git a/include/base/internal/cef_atomicops_x86_msvc.h b/include/base/internal/cef_atomicops_x86_msvc.h new file mode 100644 index 000000000..12bb0f468 --- /dev/null +++ b/include/base/internal/cef_atomicops_x86_msvc.h @@ -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 + +#include + +#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(ptr), + static_cast(new_value), + static_cast(old_value)); + return static_cast(result); +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + LONG result = _InterlockedExchange( + reinterpret_cast(ptr), + static_cast(new_value)); + return static_cast(result); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return _InterlockedExchangeAdd( + reinterpret_cast(ptr), + static_cast(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(ptr), + reinterpret_cast(new_value), reinterpret_cast(old_value)); + return reinterpret_cast(result); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + PVOID result = InterlockedExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value)); + return reinterpret_cast(result); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return InterlockedExchangeAdd64( + reinterpret_cast(ptr), + static_cast(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_ diff --git a/include/base/internal/cef_bind_internal.h b/include/base/internal/cef_bind_internal.h new file mode 100644 index 000000000..725405a05 --- /dev/null +++ b/include/base/internal/cef_bind_internal.h @@ -0,0 +1,2811 @@ +// 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. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ + +#include "include/base/cef_bind_helpers.h" +#include "include/base/cef_build.h" +#include "include/base/cef_template_util.h" +#include "include/base/cef_weak_ptr.h" +#include "include/base/internal/cef_callback_internal.h" +#include "include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h" + +#if defined(OS_WIN) +#include "include/base/internal/cef_bind_internal_win.h" +#endif + +namespace base { +namespace internal { + +// See base/callback.h for user documentation. +// +// +// CONCEPTS: +// Runnable -- A type (really a type class) that has a single Run() method +// and a RunType typedef that corresponds to the type of Run(). +// A Runnable can declare that it should treated like a method +// call by including a typedef named IsMethod. The value of +// this typedef is NOT inspected, only the existence. When a +// Runnable declares itself a method, Bind() will enforce special +// refcounting + WeakPtr handling semantics for the first +// parameter which is expected to be an object. +// Functor -- A copyable type representing something that should be called. +// All function pointers, Callback<>, and Runnables are functors +// even if the invocation syntax differs. +// RunType -- A function type (as opposed to function _pointer_ type) for +// a Run() function. Usually just a convenience typedef. +// (Bound)ArgsType -- A function type that is being (ab)used to store the +// types of set of arguments. The "return" type is always +// void here. We use this hack so that we do not need +// a new type name for each arity of type. (eg., +// BindState1, BindState2). This makes forward +// declarations and friending much much easier. +// +// Types: +// RunnableAdapter<> -- Wraps the various "function" pointer types into an +// object that adheres to the Runnable interface. +// There are |3*ARITY| RunnableAdapter types. +// FunctionTraits<> -- Type traits that unwrap a function signature into a +// a set of easier to use typedefs. Used mainly for +// compile time asserts. +// There are |ARITY| FunctionTraits types. +// ForceVoidReturn<> -- Helper class for translating function signatures to +// equivalent forms with a "void" return type. +// There are |ARITY| ForceVoidReturn types. +// FunctorTraits<> -- Type traits used determine the correct RunType and +// RunnableType for a Functor. This is where function +// signature adapters are applied. +// There are |ARITY| ForceVoidReturn types. +// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable +// type class that represents the underlying Functor. +// There are |O(1)| MakeRunnable types. +// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// Handle the differing syntaxes needed for WeakPtr<> support, +// and for ignoring return values. This is separate from +// Invoker to avoid creating multiple version of Invoker<> +// which grows at O(n^2) with the arity. +// There are |k*ARITY| InvokeHelper types. +// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// There are |(ARITY^2 + ARITY)/2| Invoketypes. +// BindState<> -- Stores the curried parameters, and is the main entry point +// into the Bind() system, doing most of the type resolution. +// There are ARITY BindState types. + +// RunnableAdapter<> +// +// The RunnableAdapter<> templates provide a uniform interface for invoking +// a function pointer, method pointer, or const method pointer. The adapter +// exposes a Run() method with an appropriate signature. Using this wrapper +// allows for writing code that supports all three pointer types without +// undue repetition. Without it, a lot of code would need to be repeated 3 +// times. +// +// For method pointers and const method pointers the first argument to Run() +// is considered to be the received of the method. This is similar to STL's +// mem_fun(). +// +// This class also exposes a RunType typedef that is the function type of the +// Run() function. +// +// If and only if the wrapper contains a method or const method pointer, an +// IsMethod typedef is exposed. The existence of this typedef (NOT the value) +// marks that the wrapper should be considered a method wrapper. + +template +class RunnableAdapter; + +// Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(*function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (*function_)(); +}; + +// Method: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)()) + : method_(method) { + } + + R Run(T* object) { + return (object->*method_)(); + } + + private: + R (T::*method_)(); +}; + +// Const Method: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)() const) + : method_(method) { + } + + R Run(const T* object) { + return (object->*method_)(); + } + + private: + R (T::*method_)() const; +}; + +// Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(*function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(CallbackForward(a1)); + } + + private: + R (*function_)(A1); +}; + +// Method: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1) { + return (object->*method_)(CallbackForward(a1)); + } + + private: + R (T::*method_)(A1); +}; + +// Const Method: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1) { + return (object->*method_)(CallbackForward(a1)); + } + + private: + R (T::*method_)(A1) const; +}; + +// Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(*function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (*function_)(A1, A2); +}; + +// Method: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (T::*method_)(A1, A2); +}; + +// Const Method: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (T::*method_)(A1, A2) const; +}; + +// Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(*function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (*function_)(A1, A2, A3); +}; + +// Method: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (T::*method_)(A1, A2, A3); +}; + +// Const Method: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (T::*method_)(A1, A2, A3) const; +}; + +// Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (*function_)(A1, A2, A3, A4); +}; + +// Method: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (T::*method_)(A1, A2, A3, A4); +}; + +// Const Method: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (T::*method_)(A1, A2, A3, A4) const; +}; + +// Function: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5); +}; + +// Method: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5); +}; + +// Const Method: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5) const; +}; + +// Function: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5, A6); +}; + +// Method: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6); +}; + +// Const Method: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6) const; +}; + +// Function: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Method: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Const Method: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7) const; +}; + + +// FunctionTraits<> +// +// Breaks a function signature apart into typedefs for easier introspection. +template +struct FunctionTraits; + +template +struct FunctionTraits { + typedef R ReturnType; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; + typedef A7 A7Type; +}; + + +// ForceVoidReturn<> +// +// Set of templates that support forcing the function return type to void. +template +struct ForceVoidReturn; + +template +struct ForceVoidReturn { + typedef void(RunType)(); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5, A6); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5, A6, A7); +}; + + +// FunctorTraits<> +// +// See description at top of file. +template +struct FunctorTraits { + typedef RunnableAdapter RunnableType; + typedef typename RunnableType::RunType RunType; +}; + +template +struct FunctorTraits > { + typedef typename FunctorTraits::RunnableType RunnableType; + typedef typename ForceVoidReturn< + typename RunnableType::RunType>::RunType RunType; +}; + +template +struct FunctorTraits > { + typedef Callback RunnableType; + typedef typename Callback::RunType RunType; +}; + + +// MakeRunnable<> +// +// Converts a passed in functor to a RunnableType using type inference. + +template +typename FunctorTraits::RunnableType MakeRunnable(const T& t) { + return RunnableAdapter(t); +} + +template +typename FunctorTraits::RunnableType +MakeRunnable(const IgnoreResultHelper& t) { + return MakeRunnable(t.functor_); +} + +template +const typename FunctorTraits >::RunnableType& +MakeRunnable(const Callback& t) { + DCHECK(!t.is_null()); + return t; +} + + +// InvokeHelper<> +// +// There are 3 logical InvokeHelper<> specializations: normal, void-return, +// WeakCalls. +// +// The normal type just calls the underlying runnable. +// +// We need a InvokeHelper to handle void return types in order to support +// IgnoreResult(). Normally, if the Runnable's RunType had a void return, +// the template system would just accept "return functor.Run()" ignoring +// the fact that a void function is being used with return. This piece of +// sugar breaks though when the Runnable's RunType is not void. Thus, we +// need a partial specialization to change the syntax to drop the "return" +// from the invocation call. +// +// WeakCalls similarly need special syntax that is applied to the first +// argument to check if they should no-op themselves. +template +struct InvokeHelper; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable) { + return runnable.Run(); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable) { + runnable.Run(); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1) { + return runnable.Run(CallbackForward(a1)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1) { + runnable.Run(CallbackForward(a1)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get()); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2) { + runnable.Run(CallbackForward(a1), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5, A6 a6) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6, A7 a7) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6, A7 a7) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5, A6 a6, A7 a7) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); + } +}; + +#if !defined(_MSC_VER) + +template +struct InvokeHelper { + // WeakCalls are only supported for functions with a void return type. + // Otherwise, the function result would be undefined if the the WeakPtr<> + // is invalidated. + COMPILE_ASSERT(is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); +}; + +#endif + +// Invoker<> +// +// See description at the top of the file. +template +struct Invoker; + +// Arity 0 -> 0. +template +struct Invoker<0, StorageType, R()> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper + ::MakeItSo(storage->runnable_); + } +}; + +// Arity 1 -> 1. +template +struct Invoker<0, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1)> + ::MakeItSo(storage->runnable_, CallbackForward(x1)); + } +}; + +// Arity 1 -> 0. +template +struct Invoker<1, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1)); + } +}; + +// Arity 2 -> 2. +template +struct Invoker<0, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 2 -> 1. +template +struct Invoker<1, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 2 -> 0. +template +struct Invoker<2, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 3 -> 3. +template +struct Invoker<0, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 2. +template +struct Invoker<1, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 1. +template +struct Invoker<2, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 0. +template +struct Invoker<3, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 4 -> 4. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 3. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 2. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 1. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 0. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 5 -> 5. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 4. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 3. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 2. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 1. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 0. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 6 -> 6. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 5. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 4. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 3. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 2. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 1. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 0. +template +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 7 -> 7. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 6. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 5. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 4. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 3. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 2. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 1. +template +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + return InvokeHelper::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 0. +template +struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + typename Bound7UnwrapTraits::ForwardType x7 = + Bound7UnwrapTraits::Unwrap(storage->p7_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + + +// BindState<> +// +// This stores all the state passed into Bind() and is also where most +// of the template resolution magic occurs. +// +// Runnable is the functor we are binding arguments to. +// RunType is type of the Run() function that the Invoker<> should use. +// Normally, this is the same as the RunType of the Runnable, but it can +// be different if an adapter like IgnoreResult() has been used. +// +// BoundArgsType contains the storage type for all the bound arguments by +// (ab)using a function type. +template +struct BindState; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef false_type IsWeakCall; + typedef Invoker<0, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + explicit BindState(const Runnable& runnable) + : runnable_(runnable) { + } + + virtual ~BindState() { } + + RunnableType runnable_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<1, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1) + : runnable_(runnable), + p1_(p1) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<2, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2) + : runnable_(runnable), + p1_(p1), + p2_(p2) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<3, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<4, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<5, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<6, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + typedef UnwrapTraits Bound6UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5, const P6& p6) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; + P6 p6_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<7, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + typedef UnwrapTraits Bound6UnwrapTraits; + typedef UnwrapTraits Bound7UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5, const P6& p6, const P7& p7) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6), + p7_(p7) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; + P6 p6_; + P7 p7_; +}; + +} // namespace internal +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ diff --git a/include/base/internal/cef_bind_internal_win.h b/include/base/internal/cef_bind_internal_win.h new file mode 100644 index 000000000..9fde64649 --- /dev/null +++ b/include/base/internal/cef_bind_internal_win.h @@ -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 +class RunnableAdapter; + +// __stdcall Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(__stdcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (__stdcall *function_)(); +}; + +// __fastcall Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(__fastcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (__fastcall *function_)(); +}; + +// __stdcall Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(__stdcall *function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(a1); + } + + private: + R (__stdcall *function_)(A1); +}; + +// __fastcall Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(__fastcall *function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(a1); + } + + private: + R (__fastcall *function_)(A1); +}; + +// __stdcall Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__stdcall *function_)(A1, A2); +}; + +// __fastcall Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__fastcall *function_)(A1, A2); +}; + +// __stdcall Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__stdcall *function_)(A1, A2, A3); +}; + +// __fastcall Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__fastcall *function_)(A1, A2, A3); +}; + +// __stdcall Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4); +}; + +// __fastcall Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4); +}; + +// __stdcall Function: Arity 5. +template +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5); +}; + +// __fastcall Function: Arity 5. +template +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5); +}; + +// __stdcall Function: Arity 6. +template +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::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 +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::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 +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::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 +class RunnableAdapter { + 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::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::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_ diff --git a/include/base/internal/cef_callback_internal.h b/include/base/internal/cef_callback_internal.h new file mode 100644 index 000000000..34a1b5f44 --- /dev/null +++ b/include/base/internal/cef_callback_internal.h @@ -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 + +#include "include/base/cef_ref_counted.h" +#include "include/base/cef_scoped_ptr.h" + +template +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 { + protected: + friend class RefCountedThreadSafe; + 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 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 struct IsMoveOnlyType { + template + static YesType Test(const typename U::MoveOnlyTypeForCPP03*); + + template + static NoType Test(...); + + static const bool value = sizeof(Test(0)) == sizeof(YesType) && + !is_const::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 ::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 +struct CallbackParamTraits { + 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 +struct CallbackParamTraits { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// See comment for CallbackParamTraits. +template +struct CallbackParamTraits { + 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 +struct CallbackParamTraits { + 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 enable_if::value, T>::type& CallbackForward(T& t) { + return t; +} + +template +typename enable_if::value, T>::type CallbackForward(T& t) { + return t.Pass(); +} + +} // namespace internal +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_ diff --git a/include/base/internal/cef_lock_impl.h b/include/base/internal/cef_lock_impl.h new file mode 100644 index 000000000..bd708c20d --- /dev/null +++ b/include/base/internal/cef_lock_impl.h @@ -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 +#elif defined(OS_POSIX) +#include +#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_ diff --git a/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h b/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h new file mode 100644 index 000000000..c643a9ecd --- /dev/null +++ b/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h @@ -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 +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::value && + (is_convertible::value || + is_convertible::value)) + }; +#endif +}; + +template +struct ParamsUseScopedRefptrCorrectly { + enum { value = 0 }; +}; + +template <> +struct ParamsUseScopedRefptrCorrectly { + enum { value = 1 }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !NeedsScopedRefptrButGetsRawPtr::value }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +} // namespace internal + +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/include/base/internal/cef_thread_checker_impl.h b/include/base/internal/cef_thread_checker_impl.h new file mode 100644 index 000000000..e74bcf8ac --- /dev/null +++ b/include/base/internal/cef_thread_checker_impl.h @@ -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_ diff --git a/include/capi/cef_base_capi.h b/include/capi/cef_base_capi.h index dc5992660..edeef3c0e 100644 --- a/include/capi/cef_base_capi.h +++ b/include/capi/cef_base_capi.h @@ -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; diff --git a/include/cef_base.h b/include/cef_base.h index 0b6b445da..c237b9e8d 100644 --- a/include/cef_base.h +++ b/include/cef_base.h @@ -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(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_ diff --git a/include/cef_runnable.h b/include/cef_runnable.h index 37ad0efe2..32e2df17a 100644 --- a/include/cef_runnable.h +++ b/include/cef_runnable.h @@ -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 ----------------------------------------------------- // diff --git a/include/cef_trace.h b/include/cef_trace.h index ebcb6a4dc..5b977c6e5 100644 --- a/include/cef_trace.h +++ b/include/cef_trace.h @@ -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 callback); diff --git a/include/internal/cef_linux.h b/include/internal/cef_linux.h index f0a443306..6238397a3 100644 --- a/include/internal/cef_linux.h +++ b/include/internal/cef_linux.h @@ -32,42 +32,9 @@ #define CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ #pragma once -#if defined(OS_LINUX) -#include #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 { } }; -#endif // OS_LINUX - #endif // CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ diff --git a/include/internal/cef_mac.h b/include/internal/cef_mac.h index 2e4bcbc07..8defbfb09 100644 --- a/include/internal/cef_mac.h +++ b/include/internal/cef_mac.h @@ -32,42 +32,9 @@ #define CEF_INCLUDE_INTERNAL_CEF_MAC_H_ #pragma once -#if defined(OS_MACOSX) -#include #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 { } }; -#endif // OS_MACOSX - #endif // CEF_INCLUDE_INTERNAL_CEF_MAC_H_ diff --git a/include/internal/cef_ptr.h b/include/internal/cef_ptr.h index fcbe69e5c..e38543911 100644 --- a/include/internal/cef_ptr.h +++ b/include/internal/cef_ptr.h @@ -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 +#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. //

// 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 @@ //

/// template -class CefRefPtr { +class CefRefPtr : public scoped_refptr { public: - CefRefPtr() : ptr_(NULL) { - } + typedef scoped_refptr parent; - CefRefPtr(T* p) : ptr_(p) { // NOLINT(runtime/explicit) - if (ptr_) - ptr_->AddRef(); - } + CefRefPtr() : parent() {} - CefRefPtr(const CefRefPtr& r) : ptr_(r.ptr_) { - if (ptr_) - ptr_->AddRef(); - } + CefRefPtr(T* p) : parent(p) {} - ~CefRefPtr() { - if (ptr_) - ptr_->Release(); - } + CefRefPtr(const scoped_refptr& r) : parent(r) {} - T* get() const { return ptr_; } - operator T*() const { return ptr_; } - T* operator->() const { return ptr_; } - - CefRefPtr& operator=(T* p) { - // AddRef first so that self assignment should work - if (p) - p->AddRef(); - if (ptr_ ) - ptr_ ->Release(); - ptr_ = p; - return *this; - } - - CefRefPtr& operator=(const CefRefPtr& r) { - return *this = r.ptr_; - } - - void swap(T** pp) { - T* p = ptr_; - ptr_ = *pp; - *pp = p; - } - - void swap(CefRefPtr& r) { - swap(&r.ptr_); // NOLINT(build/include_what_you_use) - } - - private: - T* ptr_; + template + CefRefPtr(const scoped_refptr& r) : parent(r) {} }; #endif // CEF_INCLUDE_INTERNAL_CEF_PTR_H_ diff --git a/include/internal/cef_thread_internal.h b/include/internal/cef_thread_internal.h new file mode 100644 index 000000000..eee2b2ae4 --- /dev/null +++ b/include/internal/cef_thread_internal.h @@ -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 +#elif defined(OS_POSIX) +#include +#include +#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_ diff --git a/include/internal/cef_win.h b/include/internal/cef_win.h index 4346f2b64..7361a3ce4 100644 --- a/include/internal/cef_win.h +++ b/include/internal/cef_win.h @@ -32,39 +32,9 @@ #define CEF_INCLUDE_INTERNAL_CEF_WIN_H_ #pragma once -#if defined(OS_WIN) -#include #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 { } }; -#endif // OS_WIN - #endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_ diff --git a/include/wrapper/cef_byte_read_handler.h b/include/wrapper/cef_byte_read_handler.h index 5060541f5..559cdd818 100644 --- a/include/wrapper/cef_byte_read_handler.h +++ b/include/wrapper/cef_byte_read_handler.h @@ -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 source_; - IMPLEMENT_REFCOUNTING(CefByteReadHandler); - IMPLEMENT_LOCKING(CefByteReadHandler); + base::Lock lock_; + IMPLEMENT_REFCOUNTING(CefByteReadHandler); DISALLOW_COPY_AND_ASSIGN(CefByteReadHandler); }; diff --git a/include/wrapper/cef_closure_task.h b/include/wrapper/cef_closure_task.h new file mode 100644 index 000000000..95b7c2a52 --- /dev/null +++ b/include/wrapper/cef_closure_task.h @@ -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 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 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_ diff --git a/include/wrapper/cef_helpers.h b/include/wrapper/cef_helpers.h index 352eb3f59..3624c74db 100644 --- a/include/wrapper/cef_helpers.h +++ b/include/wrapper/cef_helpers.h @@ -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[]) { diff --git a/include/wrapper/cef_stream_resource_handler.h b/include/wrapper/cef_stream_resource_handler.h index 8718c7f1b..c2ff30430 100644 --- a/include/wrapper/cef_stream_resource_handler.h +++ b/include/wrapper/cef_stream_resource_handler.h @@ -97,7 +97,6 @@ class CefStreamResourceHandler : public CefResourceHandler { #endif IMPLEMENT_REFCOUNTING(CefStreamResourceHandler); - DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler); }; diff --git a/include/wrapper/cef_xml_object.h b/include/wrapper/cef_xml_object.h index 21f54700f..4f489f292 100644 --- a/include/wrapper/cef_xml_object.h +++ b/include/wrapper/cef_xml_object.h @@ -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); }; diff --git a/include/wrapper/cef_zip_archive.h b/include/wrapper/cef_zip_archive.h index 1d8233839..9113fe5f1 100644 --- a/include/wrapper/cef_zip_archive.h +++ b/include/wrapper/cef_zip_archive.h @@ -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 @@ -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); }; diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 83f5d4b8f..1ef3e3cff 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -1803,7 +1803,7 @@ void CefBrowserHostImpl::DragTargetDragEnter(CefRefPtr drag_data, } CefDragDataImpl* data_impl = static_cast(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); diff --git a/libcef/browser/menu_creator.cc b/libcef/browser/menu_creator.cc index fdfe1799a..80291ec23 100644 --- a/libcef/browser/menu_creator.cc +++ b/libcef/browser/menu_creator.cc @@ -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 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; diff --git a/libcef/browser/menu_model_impl.cc b/libcef/browser/menu_model_impl.cc index f8c4147a9..babe2509b 100644 --- a/libcef/browser/menu_model_impl.cc +++ b/libcef/browser/menu_model_impl.cc @@ -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) { diff --git a/libcef/browser/resource_request_job.cc b/libcef/browser/resource_request_job.cc index af53a2ce0..bd6f418eb 100644 --- a/libcef/browser/resource_request_job.cc +++ b/libcef/browser/resource_request_job.cc @@ -143,7 +143,7 @@ class CefResourceRequestJobCallback : public CefCallback { net::IOBuffer* dest_; int dest_size_; - IMPLEMENT_REFCOUNTING(Callback); + IMPLEMENT_REFCOUNTING(CefResourceRequestJobCallback); }; CefResourceRequestJob::CefResourceRequestJob( diff --git a/libcef/browser/stream_impl.cc b/libcef/browser/stream_impl.cc index d434adcba..472b442a9 100644 --- a/libcef/browser/stream_impl.cc +++ b/libcef/browser/stream_impl.cc @@ -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(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(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(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); diff --git a/libcef/browser/stream_impl.h b/libcef/browser/stream_impl.h index d1aed4a8c..f07eebaab 100644 --- a/libcef/browser/stream_impl.h +++ b/libcef/browser/stream_impl.h @@ -6,9 +6,12 @@ #define CEF_LIBCEF_BROWSER_STREAM_IMPL_H_ #pragma once +#include "include/cef_stream.h" + #include #include -#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. diff --git a/libcef/browser/xml_reader_impl.h b/libcef/browser/xml_reader_impl.h index b81733ca3..5f8af1629 100644 --- a/libcef/browser/xml_reader_impl.h +++ b/libcef/browser/xml_reader_impl.h @@ -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_ diff --git a/libcef/common/base_impl.cc b/libcef/common/base_impl.cc index a3b980f64..483225dde 100644 --- a/libcef/common/base_impl.cc +++ b/libcef/common/base_impl.cc @@ -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 +} diff --git a/libcef/common/drag_data_impl.cc b/libcef/common/drag_data_impl.cc index ccb7cb1d6..f5c42dfa5 100644 --- a/libcef/common/drag_data_impl.cc +++ b/libcef/common/drag_data_impl.cc @@ -32,65 +32,65 @@ CefRefPtr CefDragData::Create() { CefRefPtr 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 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 writer) { } bool CefDragDataImpl::GetFileNames(std::vector& 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& 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; diff --git a/libcef/common/drag_data_impl.h b/libcef/common/drag_data_impl.h index 21717478d..61e6d14aa 100644 --- a/libcef/common/drag_data_impl.h +++ b/libcef/common/drag_data_impl.h @@ -6,9 +6,11 @@ #define CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_ #pragma once +#include "include/cef_drag_data.h" + #include -#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_ diff --git a/libcef/common/request_impl.cc b/libcef/common/request_impl.cc index 5462a0c98..812df1f76 100644 --- a/libcef/common/request_impl.cc +++ b/libcef/common/request_impl.cc @@ -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 CefRequestImpl::GetPostData() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return postdata_; } void CefRequestImpl::SetPostData(CefRefPtr 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 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 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 element) { bool CefPostDataImpl::AddElement(CefRefPtr 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 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 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 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 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 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 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(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; diff --git a/libcef/common/request_impl.h b/libcef/common/request_impl.h index 8bc44c783..f9cfdfc46 100644 --- a/libcef/common/request_impl.h +++ b/libcef/common/request_impl.h @@ -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_ diff --git a/libcef/common/response_impl.cc b/libcef/common/response_impl.cc index 3f0646ec6..903f007bb 100644 --- a/libcef/common/response_impl.cc +++ b/libcef/common/response_impl.cc @@ -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; } diff --git a/libcef/common/response_impl.h b/libcef/common/response_impl.h index fd117153a..084cabce3 100644 --- a/libcef/common/response_impl.h +++ b/libcef/common/response_impl.h @@ -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_ diff --git a/libcef/common/scheme_registrar_impl.cc b/libcef/common/scheme_registrar_impl.cc index c9ff116b9..26e841742 100644 --- a/libcef/common/scheme_registrar_impl.cc +++ b/libcef/common/scheme_registrar_impl.cc @@ -48,7 +48,7 @@ void CefSchemeRegistrarImpl::GetStandardSchemes( } bool CefSchemeRegistrarImpl::VerifyRefCount() { - return (GetRefCt() == 1); + return HasOneRef(); } void CefSchemeRegistrarImpl::Detach() { diff --git a/libcef/common/tracker.cc b/libcef/common/tracker.cc index 6ed19e891..0a94ddb10 100644 --- a/libcef/common/tracker.cc +++ b/libcef/common/tracker.cc @@ -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(); diff --git a/libcef/common/tracker.h b/libcef/common/tracker.h index 741d5c5e1..3491bb713 100644 --- a/libcef/common/tracker.h +++ b/libcef/common/tracker.h @@ -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_ diff --git a/libcef/renderer/dom_document_impl.cc b/libcef/renderer/dom_document_impl.cc index 46aeebc98..6357c6952 100644 --- a/libcef/renderer/dom_document_impl.cc +++ b/libcef/renderer/dom_document_impl.cc @@ -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(); diff --git a/libcef/renderer/dom_event_impl.cc b/libcef/renderer/dom_event_impl.cc index 3559570b2..e19232f23 100644 --- a/libcef/renderer/dom_event_impl.cc +++ b/libcef/renderer/dom_event_impl.cc @@ -133,7 +133,7 @@ CefRefPtr 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()); diff --git a/libcef/renderer/render_urlrequest_impl.h b/libcef/renderer/render_urlrequest_impl.h index b529b100c..50d894caf 100644 --- a/libcef/renderer/render_urlrequest_impl.h +++ b/libcef/renderer/render_urlrequest_impl.h @@ -31,7 +31,7 @@ class CefRenderURLRequest : public CefURLRequest { scoped_refptr context_; - IMPLEMENT_REFCOUNTING(CefBrowserURLRequest); + IMPLEMENT_REFCOUNTING(CefRenderURLRequest); }; #endif // CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_ diff --git a/libcef_dll/base/cef_atomicops_x86_gcc.cc b/libcef_dll/base/cef_atomicops_x86_gcc.cc new file mode 100644 index 000000000..4471eedaf --- /dev/null +++ b/libcef_dll/base/cef_atomicops_x86_gcc.cc @@ -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 +#include + +#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_ diff --git a/libcef_dll/base/cef_bind_helpers.cc b/libcef_dll/base/cef_bind_helpers.cc new file mode 100644 index 000000000..b65f5f31f --- /dev/null +++ b/libcef_dll/base/cef_bind_helpers.cc @@ -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 diff --git a/libcef_dll/base/cef_callback_helpers.cc b/libcef_dll/base/cef_callback_helpers.cc new file mode 100644 index 000000000..726104c7b --- /dev/null +++ b/libcef_dll/base/cef_callback_helpers.cc @@ -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 diff --git a/libcef_dll/base/cef_callback_internal.cc b/libcef_dll/base/cef_callback_internal.cc new file mode 100644 index 000000000..1da9ac855 --- /dev/null +++ b/libcef_dll/base/cef_callback_internal.cc @@ -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 diff --git a/libcef_dll/base/cef_lock.cc b/libcef_dll/base/cef_lock.cc new file mode 100644 index 000000000..f0a2cd44a --- /dev/null +++ b/libcef_dll/base/cef_lock.cc @@ -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 diff --git a/libcef_dll/base/cef_lock_impl.cc b/libcef_dll/base/cef_lock_impl.cc new file mode 100644 index 000000000..97a03d192 --- /dev/null +++ b/libcef_dll/base/cef_lock_impl.cc @@ -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 +#include + +#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) diff --git a/libcef_dll/base/cef_logging.cc b/libcef_dll/base/cef_logging.cc index 7904633e2..a828b8fad 100644 --- a/libcef_dll/base/cef_logging.cc +++ b/libcef_dll/base/cef_logging.cc @@ -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 diff --git a/libcef_dll/base/cef_ref_counted.cc b/libcef_dll/base/cef_ref_counted.cc new file mode 100644 index 000000000..76b44b5b3 --- /dev/null +++ b/libcef_dll/base/cef_ref_counted.cc @@ -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(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 diff --git a/libcef_dll/base/cef_thread_checker_impl.cc b/libcef_dll/base/cef_thread_checker_impl.cc new file mode 100644 index 000000000..d3193a28d --- /dev/null +++ b/libcef_dll/base/cef_thread_checker_impl.cc @@ -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 diff --git a/libcef_dll/base/cef_thread_collision_warner.cc b/libcef_dll/base/cef_thread_collision_warner.cc new file mode 100644 index 000000000..794ab64a4 --- /dev/null +++ b/libcef_dll/base/cef_thread_collision_warner.cc @@ -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(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 diff --git a/libcef_dll/base/cef_weak_ptr.cc b/libcef_dll/base/cef_weak_ptr.cc new file mode 100644 index 000000000..f8a9779d5 --- /dev/null +++ b/libcef_dll/base/cef_weak_ptr.cc @@ -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 diff --git a/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc index 01fd63e2a..e0ec4d3db 100644 --- a/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc @@ -40,7 +40,7 @@ CefAllowCertificateErrorCallbackCppToC::CefAllowCertificateErrorCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/app_cpptoc.cc b/libcef_dll/cpptoc/app_cpptoc.cc index 86645a110..557b3a1c8 100644 --- a/libcef_dll/cpptoc/app_cpptoc.cc +++ b/libcef_dll/cpptoc/app_cpptoc.cc @@ -119,6 +119,7 @@ CefAppCppToC::CefAppCppToC(CefApp* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/auth_callback_cpptoc.cc b/libcef_dll/cpptoc/auth_callback_cpptoc.cc index ac4118f7c..623a7c7ba 100644 --- a/libcef_dll/cpptoc/auth_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/auth_callback_cpptoc.cc @@ -59,7 +59,7 @@ CefAuthCallbackCppToC::CefAuthCallbackCppToC(CefAuthCallback* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/base_cpptoc.h b/libcef_dll/cpptoc/base_cpptoc.h index 5712de12c..fc20cb7ca 100644 --- a/libcef_dll/cpptoc/base_cpptoc.h +++ b/libcef_dll/cpptoc/base_cpptoc.h @@ -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(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(base); - return impl->class_->GetRefCt(); + return impl->class_->HasOneRef(); } - CefRefCount refct_; + CefRefCount ref_count_; Struct struct_; CefBase* class_; diff --git a/libcef_dll/cpptoc/before_download_callback_cpptoc.cc b/libcef_dll/cpptoc/before_download_callback_cpptoc.cc index 764d365e9..534fa0567 100644 --- a/libcef_dll/cpptoc/before_download_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/before_download_callback_cpptoc.cc @@ -42,7 +42,7 @@ CefBeforeDownloadCallbackCppToC::CefBeforeDownloadCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/binary_value_cpptoc.cc b/libcef_dll/cpptoc/binary_value_cpptoc.cc index 39ff57d2c..81c9109a7 100644 --- a/libcef_dll/cpptoc/binary_value_cpptoc.cc +++ b/libcef_dll/cpptoc/binary_value_cpptoc.cc @@ -128,7 +128,7 @@ CefBinaryValueCppToC::CefBinaryValueCppToC(CefBinaryValue* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/browser_cpptoc.cc b/libcef_dll/cpptoc/browser_cpptoc.cc index 472eeb263..3844a556b 100644 --- a/libcef_dll/cpptoc/browser_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_cpptoc.cc @@ -384,7 +384,7 @@ CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 2124e40f5..3577dc80e 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -812,7 +812,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc index 03d5320ee..7748d276f 100644 --- a/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc @@ -99,7 +99,7 @@ CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/callback_cpptoc.cc b/libcef_dll/cpptoc/callback_cpptoc.cc index b09cb783f..c87bd9013 100644 --- a/libcef_dll/cpptoc/callback_cpptoc.cc +++ b/libcef_dll/cpptoc/callback_cpptoc.cc @@ -47,7 +47,7 @@ CefCallbackCppToC::CefCallbackCppToC(CefCallback* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/client_cpptoc.cc b/libcef_dll/cpptoc/client_cpptoc.cc index 9b4ac4e50..c06675e09 100644 --- a/libcef_dll/cpptoc/client_cpptoc.cc +++ b/libcef_dll/cpptoc/client_cpptoc.cc @@ -288,7 +288,7 @@ CefClientCppToC::CefClientCppToC(CefClient* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/command_line_cpptoc.cc b/libcef_dll/cpptoc/command_line_cpptoc.cc index c74494063..3eda76e54 100644 --- a/libcef_dll/cpptoc/command_line_cpptoc.cc +++ b/libcef_dll/cpptoc/command_line_cpptoc.cc @@ -422,7 +422,7 @@ CefCommandLineCppToC::CefCommandLineCppToC(CefCommandLine* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/completion_callback_cpptoc.cc b/libcef_dll/cpptoc/completion_callback_cpptoc.cc index fb0ca10c3..3b8d25a85 100644 --- a/libcef_dll/cpptoc/completion_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/completion_callback_cpptoc.cc @@ -38,7 +38,7 @@ CefCompletionCallbackCppToC::CefCompletionCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc b/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc index f1a4f319a..b1924f430 100644 --- a/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc @@ -126,7 +126,7 @@ CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/context_menu_params_cpptoc.cc b/libcef_dll/cpptoc/context_menu_params_cpptoc.cc index f8dee3d2c..017dfafd1 100644 --- a/libcef_dll/cpptoc/context_menu_params_cpptoc.cc +++ b/libcef_dll/cpptoc/context_menu_params_cpptoc.cc @@ -273,7 +273,7 @@ CefContextMenuParamsCppToC::CefContextMenuParamsCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc index f486b43d0..61fbcb41e 100644 --- a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc @@ -219,7 +219,7 @@ CefCookieManagerCppToC::CefCookieManagerCppToC(CefCookieManager* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc b/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc index ddcea1197..c93c2eef4 100644 --- a/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc +++ b/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc @@ -64,7 +64,7 @@ CefCookieVisitorCppToC::CefCookieVisitorCppToC(CefCookieVisitor* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/cpptoc.h b/libcef_dll/cpptoc/cpptoc.h index 2fdda7302..8d2e48c4f 100644 --- a/libcef_dll/cpptoc/cpptoc.h +++ b/libcef_dll/cpptoc/cpptoc.h @@ -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(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(base); - return impl->class_->GetRefCt(); + return impl->class_->HasOneRef(); } + CefRefCount ref_count_; + DISALLOW_COPY_AND_ASSIGN(CefCppToC); }; diff --git a/libcef_dll/cpptoc/dialog_handler_cpptoc.cc b/libcef_dll/cpptoc/dialog_handler_cpptoc.cc index b4b6e578e..80320a36f 100644 --- a/libcef_dll/cpptoc/dialog_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/dialog_handler_cpptoc.cc @@ -65,7 +65,7 @@ CefDialogHandlerCppToC::CefDialogHandlerCppToC(CefDialogHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/dictionary_value_cpptoc.cc b/libcef_dll/cpptoc/dictionary_value_cpptoc.cc index ceff11b42..ff41d6172 100644 --- a/libcef_dll/cpptoc/dictionary_value_cpptoc.cc +++ b/libcef_dll/cpptoc/dictionary_value_cpptoc.cc @@ -571,7 +571,7 @@ CefDictionaryValueCppToC::CefDictionaryValueCppToC(CefDictionaryValue* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/display_handler_cpptoc.cc b/libcef_dll/cpptoc/display_handler_cpptoc.cc index 21467bdcf..3b950f781 100644 --- a/libcef_dll/cpptoc/display_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/display_handler_cpptoc.cc @@ -149,7 +149,7 @@ CefDisplayHandlerCppToC::CefDisplayHandlerCppToC(CefDisplayHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/domdocument_cpptoc.cc b/libcef_dll/cpptoc/domdocument_cpptoc.cc index 58fca010e..65b582722 100644 --- a/libcef_dll/cpptoc/domdocument_cpptoc.cc +++ b/libcef_dll/cpptoc/domdocument_cpptoc.cc @@ -297,7 +297,7 @@ CefDOMDocumentCppToC::CefDOMDocumentCppToC(CefDOMDocument* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/domevent_cpptoc.cc b/libcef_dll/cpptoc/domevent_cpptoc.cc index 825abe391..dbe6220e2 100644 --- a/libcef_dll/cpptoc/domevent_cpptoc.cc +++ b/libcef_dll/cpptoc/domevent_cpptoc.cc @@ -153,7 +153,7 @@ CefDOMEventCppToC::CefDOMEventCppToC(CefDOMEvent* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/domevent_listener_cpptoc.cc b/libcef_dll/cpptoc/domevent_listener_cpptoc.cc index 4eb4bd85f..6065991ec 100644 --- a/libcef_dll/cpptoc/domevent_listener_cpptoc.cc +++ b/libcef_dll/cpptoc/domevent_listener_cpptoc.cc @@ -43,7 +43,7 @@ CefDOMEventListenerCppToC::CefDOMEventListenerCppToC(CefDOMEventListener* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/domnode_cpptoc.cc b/libcef_dll/cpptoc/domnode_cpptoc.cc index 1bc7d7ef1..754d44646 100644 --- a/libcef_dll/cpptoc/domnode_cpptoc.cc +++ b/libcef_dll/cpptoc/domnode_cpptoc.cc @@ -487,7 +487,7 @@ CefDOMNodeCppToC::CefDOMNodeCppToC(CefDOMNode* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/domvisitor_cpptoc.cc b/libcef_dll/cpptoc/domvisitor_cpptoc.cc index 36188fa2d..1cb49108b 100644 --- a/libcef_dll/cpptoc/domvisitor_cpptoc.cc +++ b/libcef_dll/cpptoc/domvisitor_cpptoc.cc @@ -42,7 +42,7 @@ CefDOMVisitorCppToC::CefDOMVisitorCppToC(CefDOMVisitor* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/download_handler_cpptoc.cc b/libcef_dll/cpptoc/download_handler_cpptoc.cc index f348688da..277b632b9 100644 --- a/libcef_dll/cpptoc/download_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/download_handler_cpptoc.cc @@ -94,7 +94,7 @@ CefDownloadHandlerCppToC::CefDownloadHandlerCppToC(CefDownloadHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/download_item_callback_cpptoc.cc b/libcef_dll/cpptoc/download_item_callback_cpptoc.cc index dce397124..6870c347c 100644 --- a/libcef_dll/cpptoc/download_item_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/download_item_callback_cpptoc.cc @@ -38,7 +38,7 @@ CefDownloadItemCallbackCppToC::CefDownloadItemCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/download_item_cpptoc.cc b/libcef_dll/cpptoc/download_item_cpptoc.cc index c5fbc76b6..9612c29d8 100644 --- a/libcef_dll/cpptoc/download_item_cpptoc.cc +++ b/libcef_dll/cpptoc/download_item_cpptoc.cc @@ -278,7 +278,7 @@ CefDownloadItemCppToC::CefDownloadItemCppToC(CefDownloadItem* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/drag_data_cpptoc.cc b/libcef_dll/cpptoc/drag_data_cpptoc.cc index c040fa15a..456ddfe84 100644 --- a/libcef_dll/cpptoc/drag_data_cpptoc.cc +++ b/libcef_dll/cpptoc/drag_data_cpptoc.cc @@ -395,7 +395,7 @@ CefDragDataCppToC::CefDragDataCppToC(CefDragData* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/drag_handler_cpptoc.cc b/libcef_dll/cpptoc/drag_handler_cpptoc.cc index 25d29e7e7..35a67ef9d 100644 --- a/libcef_dll/cpptoc/drag_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/drag_handler_cpptoc.cc @@ -53,7 +53,7 @@ CefDragHandlerCppToC::CefDragHandlerCppToC(CefDragHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc index f3e938135..5fced58ce 100644 --- a/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc @@ -45,7 +45,7 @@ CefEndTracingCallbackCppToC::CefEndTracingCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc index 218c0f831..bbf81be04 100644 --- a/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc @@ -61,7 +61,7 @@ CefFileDialogCallbackCppToC::CefFileDialogCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/focus_handler_cpptoc.cc b/libcef_dll/cpptoc/focus_handler_cpptoc.cc index 16ff1a1da..9276afcbd 100644 --- a/libcef_dll/cpptoc/focus_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/focus_handler_cpptoc.cc @@ -84,7 +84,7 @@ CefFocusHandlerCppToC::CefFocusHandlerCppToC(CefFocusHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/frame_cpptoc.cc b/libcef_dll/cpptoc/frame_cpptoc.cc index b9a4e1db8..048e1a178 100644 --- a/libcef_dll/cpptoc/frame_cpptoc.cc +++ b/libcef_dll/cpptoc/frame_cpptoc.cc @@ -395,7 +395,7 @@ CefFrameCppToC::CefFrameCppToC(CefFrame* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = - 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc b/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc index 1bb25b831..2c6ed6d73 100644 --- a/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc @@ -39,7 +39,7 @@ CefGeolocationCallbackCppToC::CefGeolocationCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc b/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc index 093656c5e..1983aec2f 100644 --- a/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc @@ -89,7 +89,7 @@ CefGeolocationHandlerCppToC::CefGeolocationHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc index 22629778e..8036c6008 100644 --- a/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc @@ -50,7 +50,7 @@ CefGetGeolocationCallbackCppToC::CefGetGeolocationCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc index 80f633312..ab0471b6a 100644 --- a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc @@ -40,7 +40,7 @@ CefJSDialogCallbackCppToC::CefJSDialogCallbackCppToC(CefJSDialogCallback* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc index 43b86ad99..a0b835392 100644 --- a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc @@ -145,7 +145,7 @@ CefJSDialogHandlerCppToC::CefJSDialogHandlerCppToC(CefJSDialogHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc b/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc index f0902540e..a8822f10c 100644 --- a/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc @@ -104,7 +104,7 @@ CefKeyboardHandlerCppToC::CefKeyboardHandlerCppToC(CefKeyboardHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/life_span_handler_cpptoc.cc b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc index 7fd061c6d..d7ee3e68c 100644 --- a/libcef_dll/cpptoc/life_span_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc @@ -205,7 +205,7 @@ CefLifeSpanHandlerCppToC::CefLifeSpanHandlerCppToC(CefLifeSpanHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/list_value_cpptoc.cc b/libcef_dll/cpptoc/list_value_cpptoc.cc index 305f63bd9..638bcad11 100644 --- a/libcef_dll/cpptoc/list_value_cpptoc.cc +++ b/libcef_dll/cpptoc/list_value_cpptoc.cc @@ -522,7 +522,7 @@ CefListValueCppToC::CefListValueCppToC(CefListValue* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/load_handler_cpptoc.cc b/libcef_dll/cpptoc/load_handler_cpptoc.cc index bbde4c87a..e3829f23f 100644 --- a/libcef_dll/cpptoc/load_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/load_handler_cpptoc.cc @@ -127,7 +127,7 @@ CefLoadHandlerCppToC::CefLoadHandlerCppToC(CefLoadHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/menu_model_cpptoc.cc b/libcef_dll/cpptoc/menu_model_cpptoc.cc index f720775d5..ae45e3a5c 100644 --- a/libcef_dll/cpptoc/menu_model_cpptoc.cc +++ b/libcef_dll/cpptoc/menu_model_cpptoc.cc @@ -1014,7 +1014,7 @@ CefMenuModelCppToC::CefMenuModelCppToC(CefMenuModel* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/post_data_cpptoc.cc b/libcef_dll/cpptoc/post_data_cpptoc.cc index 5b88a0c16..3cc147e8d 100644 --- a/libcef_dll/cpptoc/post_data_cpptoc.cc +++ b/libcef_dll/cpptoc/post_data_cpptoc.cc @@ -158,7 +158,7 @@ CefPostDataCppToC::CefPostDataCppToC(CefPostData* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/post_data_element_cpptoc.cc b/libcef_dll/cpptoc/post_data_element_cpptoc.cc index 907a9cf2b..9feb5a674 100644 --- a/libcef_dll/cpptoc/post_data_element_cpptoc.cc +++ b/libcef_dll/cpptoc/post_data_element_cpptoc.cc @@ -174,7 +174,7 @@ CefPostDataElementCppToC::CefPostDataElementCppToC(CefPostDataElement* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc index 94daf9a3d..d85827829 100644 --- a/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc @@ -58,7 +58,7 @@ CefPrintDialogCallbackCppToC::CefPrintDialogCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/print_handler_cpptoc.cc b/libcef_dll/cpptoc/print_handler_cpptoc.cc index a0cf6bf62..193759e6b 100644 --- a/libcef_dll/cpptoc/print_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/print_handler_cpptoc.cc @@ -115,7 +115,7 @@ CefPrintHandlerCppToC::CefPrintHandlerCppToC(CefPrintHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/print_job_callback_cpptoc.cc b/libcef_dll/cpptoc/print_job_callback_cpptoc.cc index 4eb097349..ee1bf65fb 100644 --- a/libcef_dll/cpptoc/print_job_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/print_job_callback_cpptoc.cc @@ -37,7 +37,7 @@ CefPrintJobCallbackCppToC::CefPrintJobCallbackCppToC(CefPrintJobCallback* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/print_settings_cpptoc.cc b/libcef_dll/cpptoc/print_settings_cpptoc.cc index 4845d9f58..c2bcbb7f6 100644 --- a/libcef_dll/cpptoc/print_settings_cpptoc.cc +++ b/libcef_dll/cpptoc/print_settings_cpptoc.cc @@ -441,7 +441,7 @@ CefPrintSettingsCppToC::CefPrintSettingsCppToC(CefPrintSettings* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/process_message_cpptoc.cc b/libcef_dll/cpptoc/process_message_cpptoc.cc index 6bb3b82a9..8ee09c899 100644 --- a/libcef_dll/cpptoc/process_message_cpptoc.cc +++ b/libcef_dll/cpptoc/process_message_cpptoc.cc @@ -126,7 +126,7 @@ CefProcessMessageCppToC::CefProcessMessageCppToC(CefProcessMessage* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/quota_callback_cpptoc.cc b/libcef_dll/cpptoc/quota_callback_cpptoc.cc index 08f1a4227..e3f0217c6 100644 --- a/libcef_dll/cpptoc/quota_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/quota_callback_cpptoc.cc @@ -50,7 +50,7 @@ CefQuotaCallbackCppToC::CefQuotaCallbackCppToC(CefQuotaCallback* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/read_handler_cpptoc.cc b/libcef_dll/cpptoc/read_handler_cpptoc.cc index 119163e63..f6279ae0a 100644 --- a/libcef_dll/cpptoc/read_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/read_handler_cpptoc.cc @@ -109,7 +109,7 @@ CefReadHandlerCppToC::CefReadHandlerCppToC(CefReadHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc index 60fe7383f..203322453 100644 --- a/libcef_dll/cpptoc/render_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_handler_cpptoc.cc @@ -353,7 +353,7 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC(CefRenderHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc index ae229ed14..78a8bd9bb 100644 --- a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc @@ -315,7 +315,7 @@ CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/request_context_cpptoc.cc b/libcef_dll/cpptoc/request_context_cpptoc.cc index c25a13150..2761fedbf 100644 --- a/libcef_dll/cpptoc/request_context_cpptoc.cc +++ b/libcef_dll/cpptoc/request_context_cpptoc.cc @@ -106,7 +106,7 @@ CefRequestContextCppToC::CefRequestContextCppToC(CefRequestContext* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/request_context_handler_cpptoc.cc b/libcef_dll/cpptoc/request_context_handler_cpptoc.cc index 7a0a53763..eea653351 100644 --- a/libcef_dll/cpptoc/request_context_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/request_context_handler_cpptoc.cc @@ -44,7 +44,7 @@ CefRequestContextHandlerCppToC::CefRequestContextHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/request_cpptoc.cc b/libcef_dll/cpptoc/request_cpptoc.cc index 53524698e..7d723bb5f 100644 --- a/libcef_dll/cpptoc/request_cpptoc.cc +++ b/libcef_dll/cpptoc/request_cpptoc.cc @@ -335,7 +335,7 @@ CefRequestCppToC::CefRequestCppToC(CefRequest* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/request_handler_cpptoc.cc b/libcef_dll/cpptoc/request_handler_cpptoc.cc index 3fd862faf..779f28ec0 100644 --- a/libcef_dll/cpptoc/request_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/request_handler_cpptoc.cc @@ -392,7 +392,7 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC(CefRequestHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc index deb5af928..cbce1fbbe 100644 --- a/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc @@ -92,7 +92,7 @@ CefResourceBundleHandlerCppToC::CefResourceBundleHandlerCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/resource_handler_cpptoc.cc b/libcef_dll/cpptoc/resource_handler_cpptoc.cc index 31b2003d5..2ce961548 100644 --- a/libcef_dll/cpptoc/resource_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/resource_handler_cpptoc.cc @@ -197,7 +197,7 @@ CefResourceHandlerCppToC::CefResourceHandlerCppToC(CefResourceHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/response_cpptoc.cc b/libcef_dll/cpptoc/response_cpptoc.cc index fb8279307..38f549d7f 100644 --- a/libcef_dll/cpptoc/response_cpptoc.cc +++ b/libcef_dll/cpptoc/response_cpptoc.cc @@ -218,7 +218,7 @@ CefResponseCppToC::CefResponseCppToC(CefResponse* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc index 31134d11c..ef0f35924 100644 --- a/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc @@ -55,7 +55,7 @@ CefRunFileDialogCallbackCppToC::CefRunFileDialogCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc index bba379ff1..0dbf1ee47 100644 --- a/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc +++ b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc @@ -61,7 +61,7 @@ CefSchemeHandlerFactoryCppToC::CefSchemeHandlerFactoryCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc b/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc index c6f727a76..18a04edaa 100644 --- a/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc +++ b/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc @@ -49,7 +49,7 @@ CefSchemeRegistrarCppToC::CefSchemeRegistrarCppToC(CefSchemeRegistrar* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/stream_reader_cpptoc.cc b/libcef_dll/cpptoc/stream_reader_cpptoc.cc index 04a3b6388..c628bb8e5 100644 --- a/libcef_dll/cpptoc/stream_reader_cpptoc.cc +++ b/libcef_dll/cpptoc/stream_reader_cpptoc.cc @@ -166,7 +166,7 @@ CefStreamReaderCppToC::CefStreamReaderCppToC(CefStreamReader* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/stream_writer_cpptoc.cc b/libcef_dll/cpptoc/stream_writer_cpptoc.cc index ee236b99a..b362baf6a 100644 --- a/libcef_dll/cpptoc/stream_writer_cpptoc.cc +++ b/libcef_dll/cpptoc/stream_writer_cpptoc.cc @@ -148,7 +148,7 @@ CefStreamWriterCppToC::CefStreamWriterCppToC(CefStreamWriter* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/string_visitor_cpptoc.cc b/libcef_dll/cpptoc/string_visitor_cpptoc.cc index f021e2681..a09cefcaa 100644 --- a/libcef_dll/cpptoc/string_visitor_cpptoc.cc +++ b/libcef_dll/cpptoc/string_visitor_cpptoc.cc @@ -39,7 +39,7 @@ CefStringVisitorCppToC::CefStringVisitorCppToC(CefStringVisitor* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/task_cpptoc.cc b/libcef_dll/cpptoc/task_cpptoc.cc index fccbe7f53..d85f58b9e 100644 --- a/libcef_dll/cpptoc/task_cpptoc.cc +++ b/libcef_dll/cpptoc/task_cpptoc.cc @@ -35,6 +35,7 @@ CefTaskCppToC::CefTaskCppToC(CefTask* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/task_runner_cpptoc.cc b/libcef_dll/cpptoc/task_runner_cpptoc.cc index 671de939a..7647e0fe9 100644 --- a/libcef_dll/cpptoc/task_runner_cpptoc.cc +++ b/libcef_dll/cpptoc/task_runner_cpptoc.cc @@ -147,7 +147,7 @@ CefTaskRunnerCppToC::CefTaskRunnerCppToC(CefTaskRunner* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc index aaa50638d..8a770ec66 100644 --- a/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc +++ b/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc @@ -148,7 +148,7 @@ CefURLRequestClientCppToC::CefURLRequestClientCppToC(CefURLRequestClient* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/urlrequest_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_cpptoc.cc index 253827311..d2c08e2f5 100644 --- a/libcef_dll/cpptoc/urlrequest_cpptoc.cc +++ b/libcef_dll/cpptoc/urlrequest_cpptoc.cc @@ -146,7 +146,7 @@ CefURLRequestCppToC::CefURLRequestCppToC(CefURLRequest* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8accessor_cpptoc.cc b/libcef_dll/cpptoc/v8accessor_cpptoc.cc index 4ae2e0694..20b101e13 100644 --- a/libcef_dll/cpptoc/v8accessor_cpptoc.cc +++ b/libcef_dll/cpptoc/v8accessor_cpptoc.cc @@ -120,7 +120,7 @@ CefV8AccessorCppToC::CefV8AccessorCppToC(CefV8Accessor* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8context_cpptoc.cc b/libcef_dll/cpptoc/v8context_cpptoc.cc index de5d6709f..41614beee 100644 --- a/libcef_dll/cpptoc/v8context_cpptoc.cc +++ b/libcef_dll/cpptoc/v8context_cpptoc.cc @@ -255,7 +255,7 @@ CefV8ContextCppToC::CefV8ContextCppToC(CefV8Context* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8exception_cpptoc.cc b/libcef_dll/cpptoc/v8exception_cpptoc.cc index c566c3dfc..77380a9f8 100644 --- a/libcef_dll/cpptoc/v8exception_cpptoc.cc +++ b/libcef_dll/cpptoc/v8exception_cpptoc.cc @@ -148,7 +148,7 @@ CefV8ExceptionCppToC::CefV8ExceptionCppToC(CefV8Exception* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8handler_cpptoc.cc b/libcef_dll/cpptoc/v8handler_cpptoc.cc index b69b9f9c1..0b34e56ac 100644 --- a/libcef_dll/cpptoc/v8handler_cpptoc.cc +++ b/libcef_dll/cpptoc/v8handler_cpptoc.cc @@ -93,7 +93,7 @@ CefV8HandlerCppToC::CefV8HandlerCppToC(CefV8Handler* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc b/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc index f5cf5cff2..94b52dc72 100644 --- a/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc +++ b/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc @@ -151,7 +151,7 @@ CefV8StackFrameCppToC::CefV8StackFrameCppToC(CefV8StackFrame* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc b/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc index 7868407fe..53dd94fa0 100644 --- a/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc +++ b/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc @@ -88,7 +88,7 @@ CefV8StackTraceCppToC::CefV8StackTraceCppToC(CefV8StackTrace* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/v8value_cpptoc.cc b/libcef_dll/cpptoc/v8value_cpptoc.cc index a47aab40c..7cfacb499 100644 --- a/libcef_dll/cpptoc/v8value_cpptoc.cc +++ b/libcef_dll/cpptoc/v8value_cpptoc.cc @@ -967,7 +967,7 @@ CefV8ValueCppToC::CefV8ValueCppToC(CefV8Value* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc index cb482ddda..4df059388 100644 --- a/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc +++ b/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc @@ -88,7 +88,7 @@ CefWebPluginInfoCppToC::CefWebPluginInfoCppToC(CefWebPluginInfo* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc index 59f7e9872..254e1466e 100644 --- a/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc +++ b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc @@ -50,7 +50,7 @@ CefWebPluginInfoVisitorCppToC::CefWebPluginInfoVisitorCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc index 4d56e5540..47ad22052 100644 --- a/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc +++ b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc @@ -46,7 +46,7 @@ CefWebPluginUnstableCallbackCppToC::CefWebPluginUnstableCallbackCppToC( } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/write_handler_cpptoc.cc b/libcef_dll/cpptoc/write_handler_cpptoc.cc index 67f1eb427..4cbfb69e0 100644 --- a/libcef_dll/cpptoc/write_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/write_handler_cpptoc.cc @@ -110,7 +110,7 @@ CefWriteHandlerCppToC::CefWriteHandlerCppToC(CefWriteHandler* cls) } #ifndef NDEBUG -template<> long CefCppToC::DebugObjCt = 0; +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/xml_reader_cpptoc.cc b/libcef_dll/cpptoc/xml_reader_cpptoc.cc index 3e4eecc96..7f68aecc2 100644 --- a/libcef_dll/cpptoc/xml_reader_cpptoc.cc +++ b/libcef_dll/cpptoc/xml_reader_cpptoc.cc @@ -552,7 +552,7 @@ CefXmlReaderCppToC::CefXmlReaderCppToC(CefXmlReader* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/cpptoc/zip_reader_cpptoc.cc b/libcef_dll/cpptoc/zip_reader_cpptoc.cc index 47e608d63..ee0be27cd 100644 --- a/libcef_dll/cpptoc/zip_reader_cpptoc.cc +++ b/libcef_dll/cpptoc/zip_reader_cpptoc.cc @@ -243,7 +243,7 @@ CefZipReaderCppToC::CefZipReaderCppToC(CefZipReader* cls) } #ifndef NDEBUG -template<> long CefCppToC base::AtomicRefCount CefCppToC::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc index 1da14896e..4cc64f58b 100644 --- a/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc @@ -28,7 +28,7 @@ void CefAllowCertificateErrorCallbackCToCpp::Continue(bool allow) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/app_ctocpp.cc b/libcef_dll/ctocpp/app_ctocpp.cc index 382dbc3db..93689a4f8 100644 --- a/libcef_dll/ctocpp/app_ctocpp.cc +++ b/libcef_dll/ctocpp/app_ctocpp.cc @@ -100,6 +100,7 @@ CefRefPtr CefAppCToCpp::GetRenderProcessHandler() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/auth_callback_ctocpp.cc b/libcef_dll/ctocpp/auth_callback_ctocpp.cc index a11fb1532..1266e56ce 100644 --- a/libcef_dll/ctocpp/auth_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/auth_callback_ctocpp.cc @@ -49,7 +49,7 @@ void CefAuthCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/base_ctocpp.h b/libcef_dll/ctocpp/base_ctocpp.h index e2fb00b2c..f085183b1 100644 --- a/libcef_dll/ctocpp/base_ctocpp.h +++ b/libcef_dll/ctocpp/base_ctocpp.h @@ -60,38 +60,38 @@ class CefBaseCToCpp : public CefBase { // CefBase methods increment/decrement reference counts on both this object // and the underlying wrapped structure. - 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() { - if (!struct_->add_ref) - return 0; - return struct_->add_ref(struct_); + void UnderlyingAddRef() const { + if (struct_->add_ref) + struct_->add_ref(struct_); } - int UnderlyingRelease() { + bool UnderlyingRelease() const { if (!struct_->release) - return 0; - return struct_->release(struct_); + return false; + return struct_->release(struct_) ? true : false; } - int UnderlyingGetRefCt() { - if (!struct_->get_refct) - return 0; - return struct_->get_refct(struct_); + bool UnderlyingHasOneRef() const { + if (!struct_->has_one_ref) + return false; + return struct_->has_one_ref(struct_) ? true : false; } private: - CefRefCount refct_; + CefRefCount ref_count_; cef_base_t* struct_; DISALLOW_COPY_AND_ASSIGN(CefBaseCToCpp); diff --git a/libcef_dll/ctocpp/before_download_callback_ctocpp.cc b/libcef_dll/ctocpp/before_download_callback_ctocpp.cc index fc68f12fb..972325959 100644 --- a/libcef_dll/ctocpp/before_download_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/before_download_callback_ctocpp.cc @@ -32,7 +32,7 @@ void CefBeforeDownloadCallbackCToCpp::Continue(const CefString& download_path, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/binary_value_ctocpp.cc b/libcef_dll/ctocpp/binary_value_ctocpp.cc index 1e280e713..24bb115e5 100644 --- a/libcef_dll/ctocpp/binary_value_ctocpp.cc +++ b/libcef_dll/ctocpp/binary_value_ctocpp.cc @@ -112,7 +112,7 @@ size_t CefBinaryValueCToCpp::GetData(void* buffer, size_t buffer_size, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/browser_ctocpp.cc b/libcef_dll/ctocpp/browser_ctocpp.cc index 92bfea8f8..bfe707b44 100644 --- a/libcef_dll/ctocpp/browser_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_ctocpp.cc @@ -337,7 +337,7 @@ bool CefBrowserCToCpp::SendProcessMessage(CefProcessId target_process, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index f2de69cee..55ddc87dc 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -576,7 +576,7 @@ void CefBrowserHostCToCpp::DragSourceSystemDragEnded() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc index ad7c76550..4e7616c72 100644 --- a/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc @@ -77,7 +77,7 @@ CefRefPtr CefBrowserProcessHandlerCToCpp::GetPrintHandler() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/callback_ctocpp.cc b/libcef_dll/ctocpp/callback_ctocpp.cc index 3c0ed1341..7fe0daab5 100644 --- a/libcef_dll/ctocpp/callback_ctocpp.cc +++ b/libcef_dll/ctocpp/callback_ctocpp.cc @@ -37,7 +37,7 @@ void CefCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/client_ctocpp.cc b/libcef_dll/ctocpp/client_ctocpp.cc index 59457bf93..ec786c8a7 100644 --- a/libcef_dll/ctocpp/client_ctocpp.cc +++ b/libcef_dll/ctocpp/client_ctocpp.cc @@ -229,7 +229,7 @@ bool CefClientCToCpp::OnProcessMessageReceived(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/command_line_ctocpp.cc b/libcef_dll/ctocpp/command_line_ctocpp.cc index 0767de840..f08030da3 100644 --- a/libcef_dll/ctocpp/command_line_ctocpp.cc +++ b/libcef_dll/ctocpp/command_line_ctocpp.cc @@ -392,7 +392,7 @@ void CefCommandLineCToCpp::PrependWrapper(const CefString& wrapper) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/completion_callback_ctocpp.cc b/libcef_dll/ctocpp/completion_callback_ctocpp.cc index 9481c9101..7f6efbfd6 100644 --- a/libcef_dll/ctocpp/completion_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/completion_callback_ctocpp.cc @@ -27,7 +27,7 @@ void CefCompletionCallbackCToCpp::OnComplete() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc b/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc index b5a56b8dd..a94020cef 100644 --- a/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc @@ -110,7 +110,7 @@ void CefContextMenuHandlerCToCpp::OnContextMenuDismissed( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/context_menu_params_ctocpp.cc b/libcef_dll/ctocpp/context_menu_params_ctocpp.cc index 0bfb9d697..8748c3641 100644 --- a/libcef_dll/ctocpp/context_menu_params_ctocpp.cc +++ b/libcef_dll/ctocpp/context_menu_params_ctocpp.cc @@ -230,7 +230,7 @@ CefContextMenuParams::EditStateFlags CefContextMenuParamsCToCpp::GetEditStateFla #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc index dd9895525..c081f606f 100644 --- a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc @@ -193,7 +193,7 @@ bool CefCookieManagerCToCpp::FlushStore( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc b/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc index 00ab623e0..bd2cb3180 100644 --- a/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc +++ b/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc @@ -41,7 +41,7 @@ bool CefCookieVisitorCToCpp::Visit(const CefCookie& cookie, int count, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/ctocpp.h b/libcef_dll/ctocpp/ctocpp.h index 4f96fabf5..063fe1cfd 100644 --- a/libcef_dll/ctocpp/ctocpp.h +++ b/libcef_dll/ctocpp/ctocpp.h @@ -54,12 +54,12 @@ class CefCToCpp : public BaseName { DCHECK(str); #ifndef NDEBUG - CefAtomicIncrement(&DebugObjCt); + base::AtomicRefCountInc(&DebugObjCt); #endif } virtual ~CefCToCpp() { #ifndef NDEBUG - CefAtomicDecrement(&DebugObjCt); + base::AtomicRefCountDec(&DebugObjCt); #endif } @@ -70,46 +70,47 @@ class CefCToCpp : public BaseName { // CefBase methods increment/decrement reference counts on both this object // and the underlying wrapped structure. - 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() { - if (!struct_->base.add_ref) - return 0; - return struct_->base.add_ref(&struct_->base); + void UnderlyingAddRef() const { + if (struct_->base.add_ref) + struct_->base.add_ref(&struct_->base); } - int UnderlyingRelease() { + bool UnderlyingRelease() const { if (!struct_->base.release) - return 0; - return struct_->base.release(&struct_->base); + return false; + return struct_->base.release(&struct_->base) ? true : false; } - int UnderlyingGetRefCt() { - if (!struct_->base.get_refct) - return 0; - return struct_->base.get_refct(&struct_->base); + bool UnderlyingHasOneRef() const { + if (!struct_->base.has_one_ref) + return false; + return struct_->base.has_one_ref(&struct_->base) ? true : false; } #ifndef NDEBUG // Simple tracking of allocated objects. - static long DebugObjCt; // NOLINT(runtime/int) + static base::AtomicRefCount DebugObjCt; // NOLINT(runtime/int) #endif protected: - CefRefCount refct_; StructName* struct_; private: + CefRefCount ref_count_; + DISALLOW_COPY_AND_ASSIGN(CefCToCpp); }; diff --git a/libcef_dll/ctocpp/dialog_handler_ctocpp.cc b/libcef_dll/ctocpp/dialog_handler_ctocpp.cc index 402173ff2..27ac4468f 100644 --- a/libcef_dll/ctocpp/dialog_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/dialog_handler_ctocpp.cc @@ -63,7 +63,7 @@ bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/dictionary_value_ctocpp.cc b/libcef_dll/ctocpp/dictionary_value_ctocpp.cc index 97c519eb1..25401a289 100644 --- a/libcef_dll/ctocpp/dictionary_value_ctocpp.cc +++ b/libcef_dll/ctocpp/dictionary_value_ctocpp.cc @@ -511,7 +511,7 @@ bool CefDictionaryValueCToCpp::SetList(const CefString& key, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/display_handler_ctocpp.cc b/libcef_dll/ctocpp/display_handler_ctocpp.cc index a6a00d37f..bdeb9f054 100644 --- a/libcef_dll/ctocpp/display_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/display_handler_ctocpp.cc @@ -130,7 +130,7 @@ bool CefDisplayHandlerCToCpp::OnConsoleMessage(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/domdocument_ctocpp.cc b/libcef_dll/ctocpp/domdocument_ctocpp.cc index f9fcc23f9..a8755c9c6 100644 --- a/libcef_dll/ctocpp/domdocument_ctocpp.cc +++ b/libcef_dll/ctocpp/domdocument_ctocpp.cc @@ -249,7 +249,7 @@ CefString CefDOMDocumentCToCpp::GetCompleteURL(const CefString& partialURL) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/domevent_ctocpp.cc b/libcef_dll/ctocpp/domevent_ctocpp.cc index e55c30fbc..2119ec486 100644 --- a/libcef_dll/ctocpp/domevent_ctocpp.cc +++ b/libcef_dll/ctocpp/domevent_ctocpp.cc @@ -125,7 +125,7 @@ CefRefPtr CefDOMEventCToCpp::GetCurrentTarget() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/domevent_listener_ctocpp.cc b/libcef_dll/ctocpp/domevent_listener_ctocpp.cc index 2ff7ff9da..cabb3dd62 100644 --- a/libcef_dll/ctocpp/domevent_listener_ctocpp.cc +++ b/libcef_dll/ctocpp/domevent_listener_ctocpp.cc @@ -34,7 +34,7 @@ void CefDOMEventListenerCToCpp::HandleEvent(CefRefPtr event) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/domnode_ctocpp.cc b/libcef_dll/ctocpp/domnode_ctocpp.cc index 620c7be89..1ef950804 100644 --- a/libcef_dll/ctocpp/domnode_ctocpp.cc +++ b/libcef_dll/ctocpp/domnode_ctocpp.cc @@ -430,7 +430,7 @@ CefString CefDOMNodeCToCpp::GetElementInnerText() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/domvisitor_ctocpp.cc b/libcef_dll/ctocpp/domvisitor_ctocpp.cc index 8f10efe03..5e4820f53 100644 --- a/libcef_dll/ctocpp/domvisitor_ctocpp.cc +++ b/libcef_dll/ctocpp/domvisitor_ctocpp.cc @@ -34,7 +34,7 @@ void CefDOMVisitorCToCpp::Visit(CefRefPtr document) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/download_handler_ctocpp.cc b/libcef_dll/ctocpp/download_handler_ctocpp.cc index 9106e5500..79204fc42 100644 --- a/libcef_dll/ctocpp/download_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/download_handler_ctocpp.cc @@ -82,7 +82,7 @@ void CefDownloadHandlerCToCpp::OnDownloadUpdated(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/download_item_callback_ctocpp.cc b/libcef_dll/ctocpp/download_item_callback_ctocpp.cc index 6afc93ec7..537b5740d 100644 --- a/libcef_dll/ctocpp/download_item_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/download_item_callback_ctocpp.cc @@ -27,7 +27,7 @@ void CefDownloadItemCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/download_item_ctocpp.cc b/libcef_dll/ctocpp/download_item_ctocpp.cc index 9eeaceaee..406a0ab43 100644 --- a/libcef_dll/ctocpp/download_item_ctocpp.cc +++ b/libcef_dll/ctocpp/download_item_ctocpp.cc @@ -235,7 +235,7 @@ CefString CefDownloadItemCToCpp::GetMimeType() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/drag_data_ctocpp.cc b/libcef_dll/ctocpp/drag_data_ctocpp.cc index 34dab5fc9..a5f56d06a 100644 --- a/libcef_dll/ctocpp/drag_data_ctocpp.cc +++ b/libcef_dll/ctocpp/drag_data_ctocpp.cc @@ -352,7 +352,7 @@ void CefDragDataCToCpp::AddFile(const CefString& path, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/drag_handler_ctocpp.cc b/libcef_dll/ctocpp/drag_handler_ctocpp.cc index e4d1ef65b..4a1a9c1c3 100644 --- a/libcef_dll/ctocpp/drag_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/drag_handler_ctocpp.cc @@ -45,7 +45,7 @@ bool CefDragHandlerCToCpp::OnDragEnter(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc index a6a585014..866e1c790 100644 --- a/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc @@ -34,7 +34,7 @@ void CefEndTracingCallbackCToCpp::OnEndTracingComplete( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc index 56ec18c90..2b44f8110 100644 --- a/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc @@ -50,7 +50,7 @@ void CefFileDialogCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/focus_handler_ctocpp.cc b/libcef_dll/ctocpp/focus_handler_ctocpp.cc index 509235e17..b3b4759cb 100644 --- a/libcef_dll/ctocpp/focus_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/focus_handler_ctocpp.cc @@ -73,7 +73,7 @@ void CefFocusHandlerCToCpp::OnGotFocus(CefRefPtr browser) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/frame_ctocpp.cc b/libcef_dll/ctocpp/frame_ctocpp.cc index 9c54d3e5a..5996c119a 100644 --- a/libcef_dll/ctocpp/frame_ctocpp.cc +++ b/libcef_dll/ctocpp/frame_ctocpp.cc @@ -345,7 +345,7 @@ void CefFrameCToCpp::VisitDOM(CefRefPtr visitor) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = - 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc b/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc index c6f4bf229..94218aecf 100644 --- a/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc @@ -28,7 +28,7 @@ void CefGeolocationCallbackCToCpp::Continue(bool allow) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc b/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc index ccf71b920..396b44463 100644 --- a/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc @@ -75,7 +75,7 @@ void CefGeolocationHandlerCToCpp::OnCancelGeolocationPermission( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc index a16ee0b81..4b38beb86 100644 --- a/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc @@ -29,7 +29,7 @@ void CefGetGeolocationCallbackCToCpp::OnLocationUpdate( #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc index bdd4fedce..c0a6357cf 100644 --- a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc @@ -32,7 +32,7 @@ void CefJSDialogCallbackCToCpp::Continue(bool success, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc index bb8146590..f8f0d5415 100644 --- a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc @@ -123,7 +123,7 @@ void CefJSDialogHandlerCToCpp::OnDialogClosed(CefRefPtr browser) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc b/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc index 755fd585c..ba6aabb4d 100644 --- a/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc @@ -75,7 +75,7 @@ bool CefKeyboardHandlerCToCpp::OnKeyEvent(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/life_span_handler_ctocpp.cc b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc index cea335b3c..4b876ee98 100644 --- a/libcef_dll/ctocpp/life_span_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc @@ -150,7 +150,7 @@ void CefLifeSpanHandlerCToCpp::OnBeforeClose(CefRefPtr browser) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/list_value_ctocpp.cc b/libcef_dll/ctocpp/list_value_ctocpp.cc index f9e7ffd37..7fe3e6529 100644 --- a/libcef_dll/ctocpp/list_value_ctocpp.cc +++ b/libcef_dll/ctocpp/list_value_ctocpp.cc @@ -470,7 +470,7 @@ bool CefListValueCToCpp::SetList(int index, CefRefPtr value) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/load_handler_ctocpp.cc b/libcef_dll/ctocpp/load_handler_ctocpp.cc index 4584d0627..47953b5d9 100644 --- a/libcef_dll/ctocpp/load_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/load_handler_ctocpp.cc @@ -115,7 +115,7 @@ void CefLoadHandlerCToCpp::OnLoadError(CefRefPtr browser, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/menu_model_ctocpp.cc b/libcef_dll/ctocpp/menu_model_ctocpp.cc index d3809f6ca..3b7b0d042 100644 --- a/libcef_dll/ctocpp/menu_model_ctocpp.cc +++ b/libcef_dll/ctocpp/menu_model_ctocpp.cc @@ -833,7 +833,7 @@ bool CefMenuModelCToCpp::GetAcceleratorAt(int index, int& key_code, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/post_data_ctocpp.cc b/libcef_dll/ctocpp/post_data_ctocpp.cc index fe1a0f678..2c74a91fa 100644 --- a/libcef_dll/ctocpp/post_data_ctocpp.cc +++ b/libcef_dll/ctocpp/post_data_ctocpp.cc @@ -144,7 +144,7 @@ void CefPostDataCToCpp::RemoveElements() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/post_data_element_ctocpp.cc b/libcef_dll/ctocpp/post_data_element_ctocpp.cc index 68e67f146..f84ab4995 100644 --- a/libcef_dll/ctocpp/post_data_element_ctocpp.cc +++ b/libcef_dll/ctocpp/post_data_element_ctocpp.cc @@ -147,7 +147,7 @@ size_t CefPostDataElementCToCpp::GetBytes(size_t size, void* bytes) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc index 7e1bd378f..409e5450b 100644 --- a/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc @@ -45,7 +45,7 @@ void CefPrintDialogCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/print_handler_ctocpp.cc b/libcef_dll/ctocpp/print_handler_ctocpp.cc index d483f56aa..664e88c1f 100644 --- a/libcef_dll/ctocpp/print_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/print_handler_ctocpp.cc @@ -99,7 +99,7 @@ void CefPrintHandlerCToCpp::OnPrintReset() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/print_job_callback_ctocpp.cc b/libcef_dll/ctocpp/print_job_callback_ctocpp.cc index 4ddcc24f7..78470b5cb 100644 --- a/libcef_dll/ctocpp/print_job_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/print_job_callback_ctocpp.cc @@ -27,7 +27,7 @@ void CefPrintJobCallbackCToCpp::Continue() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/print_settings_ctocpp.cc b/libcef_dll/ctocpp/print_settings_ctocpp.cc index 5a2bbe566..5b9baba24 100644 --- a/libcef_dll/ctocpp/print_settings_ctocpp.cc +++ b/libcef_dll/ctocpp/print_settings_ctocpp.cc @@ -361,7 +361,7 @@ CefPrintSettings::DuplexMode CefPrintSettingsCToCpp::GetDuplexMode() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/process_message_ctocpp.cc b/libcef_dll/ctocpp/process_message_ctocpp.cc index 12be4737e..77983aba0 100644 --- a/libcef_dll/ctocpp/process_message_ctocpp.cc +++ b/libcef_dll/ctocpp/process_message_ctocpp.cc @@ -104,7 +104,7 @@ CefRefPtr CefProcessMessageCToCpp::GetArgumentList() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/quota_callback_ctocpp.cc b/libcef_dll/ctocpp/quota_callback_ctocpp.cc index 2921c18d3..c782ffb51 100644 --- a/libcef_dll/ctocpp/quota_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/quota_callback_ctocpp.cc @@ -38,7 +38,7 @@ void CefQuotaCallbackCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/read_handler_ctocpp.cc b/libcef_dll/ctocpp/read_handler_ctocpp.cc index c99c2df76..2230cfeef 100644 --- a/libcef_dll/ctocpp/read_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/read_handler_ctocpp.cc @@ -92,7 +92,7 @@ bool CefReadHandlerCToCpp::MayBlock() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc index f6c70cde0..3b46f9d14 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_handler_ctocpp.cc @@ -269,7 +269,7 @@ void CefRenderHandlerCToCpp::OnScrollOffsetChanged( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc index 7e8479aee..c76f3a8dd 100644 --- a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc @@ -278,7 +278,7 @@ bool CefRenderProcessHandlerCToCpp::OnProcessMessageReceived( #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/request_context_ctocpp.cc b/libcef_dll/ctocpp/request_context_ctocpp.cc index 3263ab6c7..a7bd7de01 100644 --- a/libcef_dll/ctocpp/request_context_ctocpp.cc +++ b/libcef_dll/ctocpp/request_context_ctocpp.cc @@ -90,7 +90,7 @@ CefRefPtr CefRequestContextCToCpp::GetHandler() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/request_context_handler_ctocpp.cc b/libcef_dll/ctocpp/request_context_handler_ctocpp.cc index 96fd9a5db..437366412 100644 --- a/libcef_dll/ctocpp/request_context_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/request_context_handler_ctocpp.cc @@ -31,7 +31,7 @@ CefRefPtr CefRequestContextHandlerCToCpp::GetCookieManager() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/request_ctocpp.cc b/libcef_dll/ctocpp/request_ctocpp.cc index 970a9918c..9e280c57a 100644 --- a/libcef_dll/ctocpp/request_ctocpp.cc +++ b/libcef_dll/ctocpp/request_ctocpp.cc @@ -297,7 +297,7 @@ CefRequest::TransitionType CefRequestCToCpp::GetTransitionType() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/request_handler_ctocpp.cc b/libcef_dll/ctocpp/request_handler_ctocpp.cc index 9f122681a..dcea16872 100644 --- a/libcef_dll/ctocpp/request_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/request_handler_ctocpp.cc @@ -350,7 +350,7 @@ void CefRequestHandlerCToCpp::OnRenderProcessTerminated( #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc index 1aa76ed00..fb6e31584 100644 --- a/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc @@ -50,7 +50,7 @@ bool CefResourceBundleHandlerCToCpp::GetDataResource(int resource_id, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/resource_handler_ctocpp.cc b/libcef_dll/ctocpp/resource_handler_ctocpp.cc index 45f6aea87..8920a782a 100644 --- a/libcef_dll/ctocpp/resource_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/resource_handler_ctocpp.cc @@ -130,7 +130,7 @@ void CefResourceHandlerCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/response_ctocpp.cc b/libcef_dll/ctocpp/response_ctocpp.cc index fbf649df5..6a89c1929 100644 --- a/libcef_dll/ctocpp/response_ctocpp.cc +++ b/libcef_dll/ctocpp/response_ctocpp.cc @@ -196,7 +196,7 @@ void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap) { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc index 788786cec..69b4f9063 100644 --- a/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc @@ -48,7 +48,7 @@ void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed( #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc index 4d977fcf5..19e54acbf 100644 --- a/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc +++ b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc @@ -50,7 +50,7 @@ CefRefPtr CefSchemeHandlerFactoryCToCpp::Create( #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc b/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc index adfb89ab4..6416cadf4 100644 --- a/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc +++ b/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc @@ -40,7 +40,7 @@ bool CefSchemeRegistrarCToCpp::AddCustomScheme(const CefString& scheme_name, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/stream_reader_ctocpp.cc b/libcef_dll/ctocpp/stream_reader_ctocpp.cc index f0d0622aa..62553adbc 100644 --- a/libcef_dll/ctocpp/stream_reader_ctocpp.cc +++ b/libcef_dll/ctocpp/stream_reader_ctocpp.cc @@ -148,7 +148,7 @@ bool CefStreamReaderCToCpp::MayBlock() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/stream_writer_ctocpp.cc b/libcef_dll/ctocpp/stream_writer_ctocpp.cc index ee3e1f5c4..0ae76e394 100644 --- a/libcef_dll/ctocpp/stream_writer_ctocpp.cc +++ b/libcef_dll/ctocpp/stream_writer_ctocpp.cc @@ -130,7 +130,7 @@ bool CefStreamWriterCToCpp::MayBlock() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/string_visitor_ctocpp.cc b/libcef_dll/ctocpp/string_visitor_ctocpp.cc index 528f0fcdd..d48f03c33 100644 --- a/libcef_dll/ctocpp/string_visitor_ctocpp.cc +++ b/libcef_dll/ctocpp/string_visitor_ctocpp.cc @@ -30,7 +30,7 @@ void CefStringVisitorCToCpp::Visit(const CefString& string) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/task_ctocpp.cc b/libcef_dll/ctocpp/task_ctocpp.cc index 9fbd0f053..fd4a9a5c3 100644 --- a/libcef_dll/ctocpp/task_ctocpp.cc +++ b/libcef_dll/ctocpp/task_ctocpp.cc @@ -27,6 +27,7 @@ void CefTaskCToCpp::Execute() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/task_runner_ctocpp.cc b/libcef_dll/ctocpp/task_runner_ctocpp.cc index 476b336af..f7288f914 100644 --- a/libcef_dll/ctocpp/task_runner_ctocpp.cc +++ b/libcef_dll/ctocpp/task_runner_ctocpp.cc @@ -128,7 +128,7 @@ bool CefTaskRunnerCToCpp::PostDelayedTask(CefRefPtr task, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc index 2556190bd..8e721db6a 100644 --- a/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc +++ b/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc @@ -132,7 +132,7 @@ bool CefURLRequestClientCToCpp::GetAuthCredentials(bool isProxy, #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_ctocpp.cc index c666cf6cc..709996847 100644 --- a/libcef_dll/ctocpp/urlrequest_ctocpp.cc +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.cc @@ -120,7 +120,7 @@ void CefURLRequestCToCpp::Cancel() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8accessor_ctocpp.cc b/libcef_dll/ctocpp/v8accessor_ctocpp.cc index 64f2a1249..baae7a175 100644 --- a/libcef_dll/ctocpp/v8accessor_ctocpp.cc +++ b/libcef_dll/ctocpp/v8accessor_ctocpp.cc @@ -93,7 +93,7 @@ bool CefV8AccessorCToCpp::Set(const CefString& name, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8context_ctocpp.cc b/libcef_dll/ctocpp/v8context_ctocpp.cc index b17f64ee8..8eaf6aac2 100644 --- a/libcef_dll/ctocpp/v8context_ctocpp.cc +++ b/libcef_dll/ctocpp/v8context_ctocpp.cc @@ -215,7 +215,7 @@ bool CefV8ContextCToCpp::Eval(const CefString& code, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8exception_ctocpp.cc b/libcef_dll/ctocpp/v8exception_ctocpp.cc index ff1fa1fd2..2629704c9 100644 --- a/libcef_dll/ctocpp/v8exception_ctocpp.cc +++ b/libcef_dll/ctocpp/v8exception_ctocpp.cc @@ -127,7 +127,7 @@ int CefV8ExceptionCToCpp::GetEndColumn() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8handler_ctocpp.cc b/libcef_dll/ctocpp/v8handler_ctocpp.cc index a95245e7f..afea49a55 100644 --- a/libcef_dll/ctocpp/v8handler_ctocpp.cc +++ b/libcef_dll/ctocpp/v8handler_ctocpp.cc @@ -78,7 +78,7 @@ bool CefV8HandlerCToCpp::Execute(const CefString& name, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc b/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc index aa927a448..959460314 100644 --- a/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc +++ b/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc @@ -128,7 +128,7 @@ bool CefV8StackFrameCToCpp::IsConstructor() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc b/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc index 9ea66a802..661aa337f 100644 --- a/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc +++ b/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc @@ -72,7 +72,7 @@ CefRefPtr CefV8StackTraceCToCpp::GetFrame(int index) { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/v8value_ctocpp.cc b/libcef_dll/ctocpp/v8value_ctocpp.cc index 7a73ee378..1fd71bab0 100644 --- a/libcef_dll/ctocpp/v8value_ctocpp.cc +++ b/libcef_dll/ctocpp/v8value_ctocpp.cc @@ -868,7 +868,7 @@ CefRefPtr CefV8ValueCToCpp::ExecuteFunctionWithContext( #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc index ce804a099..196b14912 100644 --- a/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc +++ b/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc @@ -77,7 +77,7 @@ CefString CefWebPluginInfoCToCpp::GetDescription() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc index 006587c3c..5811d3ef9 100644 --- a/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc +++ b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc @@ -40,7 +40,7 @@ bool CefWebPluginInfoVisitorCToCpp::Visit(CefRefPtr info, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc index ae05da0b7..eab6967e2 100644 --- a/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc +++ b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc @@ -35,7 +35,7 @@ void CefWebPluginUnstableCallbackCToCpp::IsUnstable(const CefString& path, #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/write_handler_ctocpp.cc b/libcef_dll/ctocpp/write_handler_ctocpp.cc index d8bcb0cb9..45aaec6f0 100644 --- a/libcef_dll/ctocpp/write_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/write_handler_ctocpp.cc @@ -92,7 +92,7 @@ bool CefWriteHandlerCToCpp::MayBlock() { #ifndef NDEBUG -template<> long CefCToCpp::DebugObjCt = 0; +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/xml_reader_ctocpp.cc b/libcef_dll/ctocpp/xml_reader_ctocpp.cc index 8e38f3687..4c4667b0d 100644 --- a/libcef_dll/ctocpp/xml_reader_ctocpp.cc +++ b/libcef_dll/ctocpp/xml_reader_ctocpp.cc @@ -495,7 +495,7 @@ bool CefXmlReaderCToCpp::MoveToCarryingElement() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/ctocpp/zip_reader_ctocpp.cc b/libcef_dll/ctocpp/zip_reader_ctocpp.cc index 6d6502c05..576247bdb 100644 --- a/libcef_dll/ctocpp/zip_reader_ctocpp.cc +++ b/libcef_dll/ctocpp/zip_reader_ctocpp.cc @@ -214,7 +214,7 @@ bool CefZipReaderCToCpp::Eof() { #ifndef NDEBUG -template<> long CefCToCpp base::AtomicRefCount CefCToCpp::DebugObjCt = 0; #endif diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 2ba7121f0..2c8544c1e 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -181,80 +181,91 @@ CEF_EXPORT void cef_shutdown() { #ifndef NDEBUG // Check that all wrapper objects have been destroyed - DCHECK_EQ(CefAllowCertificateErrorCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefAuthCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefBeforeDownloadCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefBinaryValueCppToC::DebugObjCt, 0); - DCHECK_EQ(CefBrowserCppToC::DebugObjCt, 0); - DCHECK_EQ(CefBrowserHostCppToC::DebugObjCt, 0); - DCHECK_EQ(CefBrowserProcessHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefCompletionCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefContextMenuHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefContextMenuParamsCppToC::DebugObjCt, 0); - DCHECK_EQ(CefCookieVisitorCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDOMDocumentCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDOMEventCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDOMEventListenerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDOMNodeCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDOMVisitorCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDialogHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDictionaryValueCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDisplayHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDownloadHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDownloadItemCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDownloadItemCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDragDataCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDragHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefEndTracingCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefFileDialogCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefFocusHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefFrameCppToC::DebugObjCt, 0); - DCHECK_EQ(CefGeolocationCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefGeolocationHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefGetGeolocationCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefJSDialogCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefJSDialogHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefKeyboardHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefLifeSpanHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefListValueCppToC::DebugObjCt, 0); - DCHECK_EQ(CefLoadHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefMenuModelCppToC::DebugObjCt, 0); - DCHECK_EQ(CefPrintDialogCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefPrintHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefPrintJobCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefPrintSettingsCppToC::DebugObjCt, 0); - DCHECK_EQ(CefProcessMessageCppToC::DebugObjCt, 0); - DCHECK_EQ(CefQuotaCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefReadHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefRenderHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefRenderProcessHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefRequestHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefResourceBundleHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefResourceHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefRunFileDialogCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefSchemeHandlerFactoryCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefSchemeRegistrarCppToC::DebugObjCt, 0); - DCHECK_EQ(CefStreamReaderCppToC::DebugObjCt, 0); - DCHECK_EQ(CefStreamWriterCppToC::DebugObjCt, 0); - DCHECK_EQ(CefStringVisitorCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefTaskCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefTaskRunnerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefURLRequestClientCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefURLRequestCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8AccessorCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8ContextCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8ExceptionCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8HandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8StackFrameCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8StackTraceCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8ValueCppToC::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginInfoCppToC::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginInfoVisitorCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginUnstableCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefWriteHandlerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefXmlReaderCppToC::DebugObjCt, 0); - DCHECK_EQ(CefZipReaderCppToC::DebugObjCt, 0); + DCHECK(base::AtomicRefCountIsZero( + &CefAllowCertificateErrorCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefAuthCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBeforeDownloadCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBinaryValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserHostCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBrowserProcessHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCompletionCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuParamsCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCookieVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventListenerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDownloadItemCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadItemCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragDataCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefEndTracingCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFileDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFocusHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFrameCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefGetGeolocationCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefKeyboardHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLifeSpanHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefListValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLoadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefMenuModelCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintJobCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefQuotaCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRenderProcessHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRequestHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefResourceBundleHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRunFileDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefSchemeHandlerFactoryCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWebPluginInfoCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginInfoVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginUnstableCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWriteHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefXmlReaderCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefZipReaderCppToC::DebugObjCt)); #endif // !NDEBUG } @@ -485,11 +496,7 @@ CEF_EXPORT int cef_begin_tracing(const cef_string_t* categories, struct _cef_completion_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Verify param: callback; type: refptr_diff - DCHECK(callback); - if (!callback) - return 0; - // Unverified params: categories + // Unverified params: categories, callback // Execute bool _retval = CefBeginTracing( diff --git a/libcef_dll/sandbox/sandbox_win.cc b/libcef_dll/sandbox/sandbox_win.cc index 5b85bf855..9f5ee10df 100644 --- a/libcef_dll/sandbox/sandbox_win.cc +++ b/libcef_dll/sandbox/sandbox_win.cc @@ -2,6 +2,9 @@ // 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 this first to avoid conflicts with cef_macros.h. +#include "base/macros.h" + #include "include/cef_sandbox_win.h" #include "sandbox/win/src/process_mitigations.h" diff --git a/libcef_dll/wrapper/cef_byte_read_handler.cc b/libcef_dll/wrapper/cef_byte_read_handler.cc index 0af1aa348..3d29feebf 100644 --- a/libcef_dll/wrapper/cef_byte_read_handler.cc +++ b/libcef_dll/wrapper/cef_byte_read_handler.cc @@ -14,7 +14,7 @@ CefByteReadHandler::CefByteReadHandler(const unsigned char* bytes, size_t size, } size_t CefByteReadHandler::Read(void* ptr, size_t size, size_t n) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); size_t s = static_cast(size_ - offset_) / size; size_t ret = std::min(n, s); memcpy(ptr, bytes_ + offset_, ret * size); @@ -24,7 +24,7 @@ size_t CefByteReadHandler::Read(void* ptr, size_t size, size_t n) { int CefByteReadHandler::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 > size_ || offset_ + offset < 0) @@ -56,11 +56,11 @@ int CefByteReadHandler::Seek(int64 offset, int whence) { } int64 CefByteReadHandler::Tell() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return offset_; } int CefByteReadHandler::Eof() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return (offset_ >= size_); } diff --git a/libcef_dll/wrapper/cef_closure_task.cc b/libcef_dll/wrapper/cef_closure_task.cc new file mode 100644 index 000000000..2a3b74254 --- /dev/null +++ b/libcef_dll/wrapper/cef_closure_task.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2014 The Chromium Embedded Framework 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/wrapper/cef_closure_task.h" +#include "include/base/cef_callback.h" + +namespace { + +class CefClosureTask : public CefTask { + public: + explicit CefClosureTask(const base::Closure& closure) + : closure_(closure) { + } + + // CefTask method + virtual void Execute() OVERRIDE { + closure_.Run(); + closure_.Reset(); + } + + private: + base::Closure closure_; + + IMPLEMENT_REFCOUNTING(CefClosureTask); + DISALLOW_COPY_AND_ASSIGN(CefClosureTask); +}; + +} // namespace + +CefRefPtr CefCreateClosureRask(const base::Closure& closure) { + return new CefClosureTask(closure); +} + +bool CefPostTask(CefThreadId threadId, const base::Closure& closure) { + return CefPostTask(threadId, new CefClosureTask(closure)); +} + +bool CefPostDelayedTask(CefThreadId threadId, const base::Closure& closure, + int64 delay_ms) { + return CefPostDelayedTask(threadId, new CefClosureTask(closure), delay_ms); +} diff --git a/libcef_dll/wrapper/cef_message_router.cc b/libcef_dll/wrapper/cef_message_router.cc index 5f28f9979..212099f31 100644 --- a/libcef_dll/wrapper/cef_message_router.cc +++ b/libcef_dll/wrapper/cef_message_router.cc @@ -138,7 +138,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { const int64 query_id_; const bool persistent_; - IMPLEMENT_REFCOUNTING(CefQueryCallbackImpl); + IMPLEMENT_REFCOUNTING(CallbackImpl); }; explicit CefMessageRouterBrowserSideImpl(const CefMessageRouterConfig& config) @@ -291,7 +291,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { // If the query isn't handled nothing should be keeping a reference to // the callback. - DCHECK(handled || callback->GetRefCt() == 1); + DCHECK(handled || callback->HasOneRef()); if (handled) { // Persist the query information until the callback executes. diff --git a/libcef_dll/wrapper/cef_xml_object.cc b/libcef_dll/wrapper/cef_xml_object.cc index 5db0b1b35..e69d67df2 100644 --- a/libcef_dll/wrapper/cef_xml_object.cc +++ b/libcef_dll/wrapper/cef_xml_object.cc @@ -168,7 +168,6 @@ CefXmlObject::~CefXmlObject() { bool CefXmlObject::Load(CefRefPtr stream, CefXmlReader::EncodingType encodingType, const CefString& URI, CefString* loadError) { - AutoLock lock_scope(this); Clear(); CefXmlObjectLoader loader(this); @@ -183,10 +182,8 @@ bool CefXmlObject::Load(CefRefPtr stream, void CefXmlObject::Set(CefRefPtr object) { DCHECK(object.get()); - AutoLock lock_scope1(this); - AutoLock lock_scope2(object); - Clear(); + name_ = object->GetName(); Append(object, true); } @@ -195,9 +192,6 @@ void CefXmlObject::Append(CefRefPtr object, bool overwriteAttributes) { DCHECK(object.get()); - AutoLock lock_scope1(this); - AutoLock lock_scope2(object); - if (object->HasChildren()) { ObjectVector children; object->GetChildren(children); @@ -220,7 +214,7 @@ void CefXmlObject::Append(CefRefPtr object, CefRefPtr CefXmlObject::Duplicate() { CefRefPtr new_obj; { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); new_obj = new CefXmlObject(name_); new_obj->Append(this, true); } @@ -228,7 +222,6 @@ CefRefPtr CefXmlObject::Duplicate() { } void CefXmlObject::Clear() { - AutoLock lock_scope(this); ClearChildren(); ClearAttributes(); } @@ -236,7 +229,7 @@ void CefXmlObject::Clear() { CefString CefXmlObject::GetName() { CefString name; { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); name = name_; } return name; @@ -247,41 +240,41 @@ bool CefXmlObject::SetName(const CefString& name) { if (name.empty()) return false; - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); name_ = name; return true; } bool CefXmlObject::HasParent() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return (parent_ != NULL); } CefRefPtr CefXmlObject::GetParent() { CefRefPtr parent; { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); parent = parent_; } return parent; } bool CefXmlObject::HasValue() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return !value_.empty(); } CefString CefXmlObject::GetValue() { CefString value; { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); value = value_; } return value; } bool CefXmlObject::SetValue(const CefString& value) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); DCHECK(children_.empty()); if (!children_.empty()) return false; @@ -290,12 +283,12 @@ bool CefXmlObject::SetValue(const CefString& value) { } bool CefXmlObject::HasAttributes() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return !attributes_.empty(); } size_t CefXmlObject::GetAttributeCount() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return attributes_.size(); } @@ -303,7 +296,7 @@ bool CefXmlObject::HasAttribute(const CefString& name) { if (name.empty()) return false; - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); AttributeMap::const_iterator it = attributes_.find(name); return (it != attributes_.end()); } @@ -312,7 +305,7 @@ CefString CefXmlObject::GetAttributeValue(const CefString& name) { DCHECK(!name.empty()); CefString value; if (!name.empty()) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); AttributeMap::const_iterator it = attributes_.find(name); if (it != attributes_.end()) value = it->second; @@ -326,7 +319,7 @@ bool CefXmlObject::SetAttributeValue(const CefString& name, if (name.empty()) return false; - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); AttributeMap::iterator it = attributes_.find(name); if (it != attributes_.end()) { it->second = value; @@ -337,30 +330,30 @@ bool CefXmlObject::SetAttributeValue(const CefString& name, } size_t CefXmlObject::GetAttributes(AttributeMap& attributes) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); attributes = attributes_; return attributes_.size(); } void CefXmlObject::ClearAttributes() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); attributes_.clear(); } bool CefXmlObject::HasChildren() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return !children_.empty(); } size_t CefXmlObject::GetChildCount() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return children_.size(); } bool CefXmlObject::HasChild(CefRefPtr child) { DCHECK(child.get()); - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); ObjectVector::const_iterator it = children_.begin(); for (; it != children_.end(); ++it) { if ((*it).get() == child.get()) @@ -374,13 +367,12 @@ bool CefXmlObject::AddChild(CefRefPtr child) { if (!child.get()) return false; - AutoLock lock_scope1(child); - - DCHECK(child->GetParent() == NULL); - if (child->GetParent() != NULL) + CefRefPtr parent = child->GetParent(); + DCHECK(!parent); + if (parent) return false; - AutoLock lock_scope2(this); + base::AutoLock lock_scope(lock_); children_.push_back(child); child->SetParent(this); @@ -390,7 +382,7 @@ bool CefXmlObject::AddChild(CefRefPtr child) { bool CefXmlObject::RemoveChild(CefRefPtr child) { DCHECK(child.get()); - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); ObjectVector::iterator it = children_.begin(); for (; it != children_.end(); ++it) { if ((*it).get() == child.get()) { @@ -403,13 +395,13 @@ bool CefXmlObject::RemoveChild(CefRefPtr child) { } size_t CefXmlObject::GetChildren(ObjectVector& children) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); children = children_; return children_.size(); } void CefXmlObject::ClearChildren() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); ObjectVector::iterator it = children_.begin(); for (; it != children_.end(); ++it) (*it)->SetParent(NULL); @@ -421,7 +413,7 @@ CefRefPtr CefXmlObject::FindChild(const CefString& name) { if (name.empty()) return NULL; - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); ObjectVector::const_iterator it = children_.begin(); for (; it != children_.end(); ++it) { if ((*it)->GetName() == name) @@ -438,7 +430,7 @@ size_t CefXmlObject::FindChildren(const CefString& name, size_t ct = 0; - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); ObjectVector::const_iterator it = children_.begin(); for (; it != children_.end(); ++it) { if ((*it)->GetName() == name) { @@ -450,7 +442,7 @@ size_t CefXmlObject::FindChildren(const CefString& name, } void CefXmlObject::SetParent(CefXmlObject* parent) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); if (parent) { DCHECK(parent_ == NULL); parent_ = parent; diff --git a/libcef_dll/wrapper/cef_zip_archive.cc b/libcef_dll/wrapper/cef_zip_archive.cc index 10479eff5..1dd8551b9 100644 --- a/libcef_dll/wrapper/cef_zip_archive.cc +++ b/libcef_dll/wrapper/cef_zip_archive.cc @@ -58,7 +58,7 @@ CefZipArchive::~CefZipArchive() { size_t CefZipArchive::Load(CefRefPtr stream, const CefString& password, bool overwriteExisting) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); CefRefPtr reader(CefZipReader::Create(stream)); if (!reader.get()) @@ -116,12 +116,12 @@ size_t CefZipArchive::Load(CefRefPtr stream, } void CefZipArchive::Clear() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); contents_.clear(); } size_t CefZipArchive::GetFileCount() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return contents_.size(); } @@ -129,7 +129,7 @@ bool CefZipArchive::HasFile(const CefString& fileName) { std::wstring str = fileName; std::transform(str.begin(), str.end(), str.begin(), towlower); - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); FileMap::const_iterator it = contents_.find(CefString(str)); return (it != contents_.end()); } @@ -139,7 +139,7 @@ CefRefPtr CefZipArchive::GetFile( std::wstring str = fileName; std::transform(str.begin(), str.end(), str.begin(), towlower); - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); FileMap::const_iterator it = contents_.find(CefString(str)); if (it != contents_.end()) return it->second; @@ -150,7 +150,7 @@ bool CefZipArchive::RemoveFile(const CefString& fileName) { std::wstring str = fileName; std::transform(str.begin(), str.end(), str.begin(), towlower); - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); FileMap::iterator it = contents_.find(CefString(str)); if (it != contents_.end()) { contents_.erase(it); @@ -160,7 +160,7 @@ bool CefZipArchive::RemoveFile(const CefString& fileName) { } size_t CefZipArchive::GetFiles(FileMap& map) { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); map = contents_; return contents_.size(); } diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index ecf7bf42c..00d32a42b 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -173,80 +173,91 @@ CEF_GLOBAL void CefShutdown() { #ifndef NDEBUG // Check that all wrapper objects have been destroyed - DCHECK_EQ(CefAllowCertificateErrorCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefAuthCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefBeforeDownloadCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefBinaryValueCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefBrowserCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefBrowserHostCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefBrowserProcessHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefCompletionCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefContextMenuHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefContextMenuParamsCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefCookieVisitorCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDOMDocumentCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDOMEventCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDOMEventListenerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDOMNodeCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDOMVisitorCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDialogHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDictionaryValueCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDisplayHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDownloadHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefDownloadItemCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDownloadItemCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDragDataCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefDragHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefEndTracingCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefFileDialogCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefFocusHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefFrameCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefGeolocationCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefGeolocationHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefGetGeolocationCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefJSDialogCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefJSDialogHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefKeyboardHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefLifeSpanHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefListValueCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefLoadHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefMenuModelCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefPrintDialogCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefPrintHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefPrintJobCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefPrintSettingsCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefProcessMessageCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefQuotaCallbackCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefReadHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefRenderHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefRenderProcessHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefRequestHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefResourceBundleHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefResourceHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefRunFileDialogCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefSchemeHandlerFactoryCppToC::DebugObjCt, 0); - DCHECK_EQ(CefSchemeRegistrarCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefStreamReaderCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefStreamWriterCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefStringVisitorCppToC::DebugObjCt, 0); - DCHECK_EQ(CefTaskCppToC::DebugObjCt, 0); - DCHECK_EQ(CefTaskRunnerCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefURLRequestCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefURLRequestClientCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8AccessorCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8ContextCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8ExceptionCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8HandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefV8StackFrameCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8StackTraceCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefV8ValueCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginInfoCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginInfoVisitorCppToC::DebugObjCt, 0); - DCHECK_EQ(CefWebPluginUnstableCallbackCppToC::DebugObjCt, 0); - DCHECK_EQ(CefWriteHandlerCppToC::DebugObjCt, 0); - DCHECK_EQ(CefXmlReaderCToCpp::DebugObjCt, 0); - DCHECK_EQ(CefZipReaderCToCpp::DebugObjCt, 0); + DCHECK(base::AtomicRefCountIsZero( + &CefAllowCertificateErrorCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefAuthCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBeforeDownloadCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBinaryValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserHostCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBrowserProcessHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCompletionCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuParamsCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCookieVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventListenerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadItemCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDownloadItemCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragDataCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefEndTracingCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFileDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFocusHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFrameCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefGetGeolocationCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefKeyboardHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLifeSpanHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefListValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLoadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefMenuModelCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintJobCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefQuotaCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRenderProcessHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRequestHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefResourceBundleHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRunFileDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefSchemeHandlerFactoryCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWebPluginInfoCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginInfoVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginUnstableCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWriteHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefXmlReaderCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefZipReaderCToCpp::DebugObjCt)); #endif // !NDEBUG } @@ -468,11 +479,7 @@ CEF_GLOBAL bool CefBeginTracing(const CefString& categories, CefRefPtr callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Verify param: callback; type: refptr_diff - DCHECK(callback.get()); - if (!callback.get()) - return false; - // Unverified params: categories + // Unverified params: categories, callback // Execute int _retval = cef_begin_tracing( diff --git a/tests/cefclient/bytes_write_handler.cpp b/tests/cefclient/bytes_write_handler.cpp index ed3f48f8f..7569417a5 100644 --- a/tests/cefclient/bytes_write_handler.cpp +++ b/tests/cefclient/bytes_write_handler.cpp @@ -19,13 +19,12 @@ BytesWriteHandler::BytesWriteHandler(size_t grow) } BytesWriteHandler::~BytesWriteHandler() { - AutoLock lock_scope(this); if (data_) free(data_); } size_t BytesWriteHandler::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(size * n) >= datasize_ && Grow(size * n) == 0) { @@ -41,7 +40,7 @@ size_t BytesWriteHandler::Write(const void* ptr, size_t size, size_t n) { int BytesWriteHandler::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) @@ -69,7 +68,7 @@ int BytesWriteHandler::Seek(int64 offset, int whence) { } int64 BytesWriteHandler::Tell() { - AutoLock lock_scope(this); + base::AutoLock lock_scope(lock_); return offset_; } @@ -78,7 +77,7 @@ int BytesWriteHandler::Flush() { } size_t BytesWriteHandler::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); diff --git a/tests/cefclient/bytes_write_handler.h b/tests/cefclient/bytes_write_handler.h index 653fcc854..24da860ba 100644 --- a/tests/cefclient/bytes_write_handler.h +++ b/tests/cefclient/bytes_write_handler.h @@ -6,6 +6,7 @@ #define CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_ #pragma once +#include "include/base/cef_lock.h" #include "include/cef_stream.h" class BytesWriteHandler : public CefWriteHandler { @@ -30,8 +31,9 @@ class BytesWriteHandler : public CefWriteHandler { int64 datasize_; int64 offset_; + base::Lock lock_; + IMPLEMENT_REFCOUNTING(BytesWriteHandler); - IMPLEMENT_LOCKING(BytesWriteHandler); }; #endif // CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_ diff --git a/tests/cefclient/cefclient_osr_widget_gtk.cpp b/tests/cefclient/cefclient_osr_widget_gtk.cpp index 5bdf44c3e..995b40f5c 100644 --- a/tests/cefclient/cefclient_osr_widget_gtk.cpp +++ b/tests/cefclient/cefclient_osr_widget_gtk.cpp @@ -17,8 +17,8 @@ #include #include -#include "include/cef_runnable.h" -#include "include/wrapper/cef_helpers.h" +#include "include/base/cef_bind.h" +#include "include/wrapper/cef_closure_task.h" namespace { @@ -1209,7 +1209,7 @@ void OSRWindow::OnCursorChange(CefRefPtr browser, void OSRWindow::Invalidate() { if (!CefCurrentlyOn(TID_UI)) { - CefPostTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Invalidate)); + CefPostTask(TID_UI, base::Bind(&OSRWindow::Invalidate, this)); return; } @@ -1221,7 +1221,7 @@ void OSRWindow::Invalidate() { // Render at 30fps. static const int kRenderDelay = 1000 / 30; - CefPostDelayedTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Render), + CefPostDelayedTask(TID_UI, base::Bind(&OSRWindow::Render, this), kRenderDelay); } diff --git a/tests/cefclient/cefclient_osr_widget_win.cpp b/tests/cefclient/cefclient_osr_widget_win.cpp index b22561778..0ec4c9712 100644 --- a/tests/cefclient/cefclient_osr_widget_win.cpp +++ b/tests/cefclient/cefclient_osr_widget_win.cpp @@ -6,8 +6,8 @@ #include -#include "include/cef_runnable.h" -#include "include/wrapper/cef_helpers.h" +#include "include/base/cef_bind.h" +#include "include/wrapper/cef_closure_task.h" #include "cefclient/resource.h" // static @@ -176,7 +176,7 @@ void OSRWindow::UpdateDragCursor(CefRefPtr browser, void OSRWindow::Invalidate() { if (!CefCurrentlyOn(TID_UI)) { - CefPostTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Invalidate)); + CefPostTask(TID_UI, base::Bind(&OSRWindow::Invalidate, this)); return; } @@ -188,7 +188,7 @@ void OSRWindow::Invalidate() { // Render at 30fps. static const int kRenderDelay = 1000 / 30; - CefPostDelayedTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Render), + CefPostDelayedTask(TID_UI, base::Bind(&OSRWindow::Render, this), kRenderDelay); } diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index b82b856c5..91077db80 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -3,17 +3,20 @@ // can be found in the LICENSE file. #include "cefclient/cefclient.h" + #include #include #include #include #include #include + +#include "include/base/cef_bind.h" #include "include/cef_app.h" #include "include/cef_browser.h" #include "include/cef_frame.h" -#include "include/cef_runnable.h" #include "include/cef_sandbox_win.h" +#include "include/wrapper/cef_closure_task.h" #include "cefclient/cefclient_osr_widget_win.h" #include "cefclient/client_handler.h" #include "cefclient/client_switches.h" @@ -234,11 +237,76 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { // Change the zoom factor on the UI thread. static void ModifyZoom(CefRefPtr browser, double delta) { - if (CefCurrentlyOn(TID_UI)) { - browser->GetHost()->SetZoomLevel( - browser->GetHost()->GetZoomLevel() + delta); + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, base::Bind(&ModifyZoom, browser, delta)); + return; + } + + browser->GetHost()->SetZoomLevel( + browser->GetHost()->GetZoomLevel() + delta); +} + +// Show a warning message on the UI thread. +static void ShowWarning(CefRefPtr browser, int id) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, base::Bind(&ShowWarning, browser, id)); + return; + } + + if (!g_handler) + return; + + std::wstring caption; + std::wstringstream message; + + switch (id) { + case ID_WARN_CONSOLEMESSAGE: + caption = L"Console Messages"; + message << L"Console messages will be written to " << + std::wstring(CefString(g_handler->GetLogFile())); + break; + case ID_WARN_DOWNLOADCOMPLETE: + case ID_WARN_DOWNLOADERROR: + caption = L"File Download"; + message << L"File \"" << + std::wstring(CefString(g_handler->GetLastDownloadFile())) << + L"\" "; + + if (id == ID_WARN_DOWNLOADCOMPLETE) + message << L"downloaded successfully."; + else + message << L"failed to download."; + break; + } + + MessageBox(g_handler->GetMainWindowHandle(), + message.str().c_str(), + caption.c_str(), + MB_OK | MB_ICONINFORMATION); +} + +// Set focus to |browser| on the UI thread. +static void SetFocusToBrowser(CefRefPtr browser) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, base::Bind(&SetFocusToBrowser, browser)); + return; + } + + if (!g_handler) + return; + + if (AppIsOffScreenRenderingEnabled()) { + // Give focus to the OSR window. + CefRefPtr osr_window = + static_cast(g_handler->GetOSRHandler().get()); + if (osr_window) + ::SetFocus(osr_window->hwnd()); } else { - CefPostTask(TID_UI, NewCefRunnableFunction(ModifyZoom, browser, delta)); + // Give focus to the browser. + browser->GetHost()->SetFocus(true); } } @@ -429,30 +497,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, g_handler->CloseAllBrowsers(false); return 0; case ID_WARN_CONSOLEMESSAGE: - if (g_handler.get()) { - std::wstringstream ss; - ss << L"Console messages will be written to " - << std::wstring(CefString(g_handler->GetLogFile())); - MessageBox(hWnd, ss.str().c_str(), L"Console Messages", - MB_OK | MB_ICONINFORMATION); - } - return 0; case ID_WARN_DOWNLOADCOMPLETE: case ID_WARN_DOWNLOADERROR: - if (g_handler.get()) { - std::wstringstream ss; - ss << L"File \"" << - std::wstring(CefString(g_handler->GetLastDownloadFile())) << - L"\" "; - - if (wmId == ID_WARN_DOWNLOADCOMPLETE) - ss << L"downloaded successfully."; - else - ss << L"failed to download."; - - MessageBox(hWnd, ss.str().c_str(), L"File Download", - MB_OK | MB_ICONINFORMATION); - } + ShowWarning(browser, wmId); return 0; case ID_FIND: if (!hFindDlg) { @@ -542,17 +589,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, return 0; case WM_SETFOCUS: - if (g_handler.get() && g_handler->GetBrowser()) { - if (AppIsOffScreenRenderingEnabled()) { - // Give focus to the OSR window. - CefRefPtr osr_window = - static_cast(g_handler->GetOSRHandler().get()); - if (osr_window) - ::SetFocus(osr_window->hwnd()); - } else { - // Give focus to the browser. - g_handler->GetBrowser()->GetHost()->SetFocus(true); - } + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser) + SetFocusToBrowser(browser); } return 0; diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 323c0ff5f..0a381eb76 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -10,13 +10,14 @@ #include #include +#include "include/base/cef_bind.h" #include "include/cef_browser.h" #include "include/cef_frame.h" #include "include/cef_path_util.h" #include "include/cef_process_util.h" -#include "include/cef_runnable.h" #include "include/cef_trace.h" #include "include/cef_url.h" +#include "include/wrapper/cef_closure_task.h" #include "include/wrapper/cef_stream_resource_handler.h" #include "cefclient/binding_test.h" #include "cefclient/cefclient.h" @@ -89,9 +90,9 @@ bool ParseTestUrl(const std::string& url, int ClientHandler::browser_count_ = 0; ClientHandler::ClientHandler() - : main_handle_(NULL), - browser_id_(0), + : browser_id_(0), is_closing_(false), + main_handle_(NULL), edit_handle_(NULL), back_handle_(NULL), forward_handle_(NULL), @@ -122,6 +123,8 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr browser, CefProcessId source_process, CefRefPtr message) { + CEF_REQUIRE_UI_THREAD(); + if (message_router_->OnProcessMessageReceived(browser, source_process, message)) { return true; @@ -146,6 +149,8 @@ void ClientHandler::OnBeforeContextMenu( CefRefPtr frame, CefRefPtr params, CefRefPtr model) { + CEF_REQUIRE_UI_THREAD(); + if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) { // Add a separator if the menu already has items. if (model->GetCount() > 0) @@ -166,6 +171,8 @@ bool ClientHandler::OnContextMenuCommand( CefRefPtr params, int command_id, EventFlags event_flags) { + CEF_REQUIRE_UI_THREAD(); + switch (command_id) { case CLIENT_ID_SHOW_DEVTOOLS: ShowDevTools(browser); @@ -186,6 +193,8 @@ bool ClientHandler::OnFileDialog(CefRefPtr browser, const CefString& default_file_name, const std::vector& accept_types, CefRefPtr callback) { + CEF_REQUIRE_UI_THREAD(); + return false; } @@ -201,8 +210,6 @@ bool ClientHandler::OnConsoleMessage(CefRefPtr browser, std::string logFile; { - AutoLock lock_scope(this); - first_message = log_file_.empty(); if (first_message) { std::stringstream ss; @@ -240,6 +247,7 @@ void ClientHandler::OnBeforeDownload( const CefString& suggested_name, CefRefPtr callback) { CEF_REQUIRE_UI_THREAD(); + // Continue the download and show the "Save As" dialog. callback->Continue(GetDownloadPath(suggested_name), true); } @@ -249,6 +257,7 @@ void ClientHandler::OnDownloadUpdated( CefRefPtr download_item, CefRefPtr callback) { CEF_REQUIRE_UI_THREAD(); + if (download_item->IsComplete()) { SetLastDownloadFile(download_item->GetFullPath()); SendNotification(NOTIFY_DOWNLOAD_COMPLETE); @@ -272,6 +281,8 @@ bool ClientHandler::OnRequestGeolocationPermission( const CefString& requesting_url, int request_id, CefRefPtr callback) { + CEF_REQUIRE_UI_THREAD(); + // Allow geolocation access from all websites. callback->Continue(true); return true; @@ -287,6 +298,7 @@ bool ClientHandler::OnJSDialog(CefRefPtr browser, const CefString& default_prompt_text, CefRefPtr callback, bool& suppress_message) { + CEF_REQUIRE_UI_THREAD(); return false; } @@ -295,10 +307,12 @@ bool ClientHandler::OnBeforeUnloadDialog( const CefString& message_text, bool is_reload, CefRefPtr callback) { + CEF_REQUIRE_UI_THREAD(); return false; } void ClientHandler::OnResetDialogState(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); } #endif // !defined(OS_LINUX) @@ -307,6 +321,8 @@ bool ClientHandler::OnPreKeyEvent(CefRefPtr browser, const CefKeyEvent& event, CefEventHandle os_event, bool* is_keyboard_shortcut) { + CEF_REQUIRE_UI_THREAD(); + if (!event.focus_on_editable_field && event.windows_key_code == 0x20) { // Special handling for the space character when an input element does not // have focus. Handling the event in OnPreKeyEvent() keeps the event from @@ -332,6 +348,8 @@ bool ClientHandler::OnBeforePopup(CefRefPtr browser, CefRefPtr& client, CefBrowserSettings& settings, bool* no_javascript_access) { + CEF_REQUIRE_IO_THREAD(); + if (browser->GetHost()->IsWindowRenderingDisabled()) { // Cancel popups in off-screen rendering mode. return true; @@ -358,8 +376,8 @@ void ClientHandler::OnAfterCreated(CefRefPtr browser) { if (mouse_cursor_change_disabled_) browser->GetHost()->SetMouseCursorChangeDisabled(true); - AutoLock lock_scope(this); - if (!browser_.get()) { + if (!GetBrowser()) { + base::AutoLock lock_scope(lock_); // We need to keep the main child window, but not popup windows browser_ = browser; browser_id_ = browser->GetIdentifier(); @@ -370,8 +388,7 @@ void ClientHandler::OnAfterCreated(CefRefPtr browser) { // Give focus to the popup browser. Perform asynchronously because the // parent window may attempt to keep focus after launching the popup. CefPostTask(TID_UI, - NewCefRunnableMethod(browser->GetHost().get(), - &CefBrowserHost::SetFocus, true)); + base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true)); } browser_count_++; @@ -383,7 +400,8 @@ bool ClientHandler::DoClose(CefRefPtr browser) { // Closing the main window requires special handling. See the DoClose() // documentation in the CEF header for a detailed destription of this // process. - if (browser_id_ == browser->GetIdentifier()) { + if (GetBrowserId() == browser->GetIdentifier()) { + base::AutoLock lock_scope(lock_); // Set a flag to indicate that the window close should be allowed. is_closing_ = true; } @@ -398,9 +416,12 @@ void ClientHandler::OnBeforeClose(CefRefPtr browser) { message_router_->OnBeforeClose(browser); - if (browser_id_ == browser->GetIdentifier()) { - // Free the browser pointer so that the browser can be destroyed - browser_ = NULL; + if (GetBrowserId() == browser->GetIdentifier()) { + { + base::AutoLock lock_scope(lock_); + // Free the browser pointer so that the browser can be destroyed + browser_ = NULL; + } if (osr_handler_.get()) { osr_handler_->OnBeforeClose(browser); @@ -481,6 +502,8 @@ bool ClientHandler::OnBeforeBrowse(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, bool is_redirect) { + CEF_REQUIRE_UI_THREAD(); + message_router_->OnBeforeBrowse(browser, frame); return false; } @@ -489,6 +512,8 @@ CefRefPtr ClientHandler::GetResourceHandler( CefRefPtr browser, CefRefPtr frame, CefRefPtr request) { + CEF_REQUIRE_IO_THREAD(); + std::string url = request->GetURL(); if (url.find(kTestOrigin) == 0) { // Handle URLs in the test origin. @@ -523,6 +548,8 @@ bool ClientHandler::OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, int64 new_size, CefRefPtr callback) { + CEF_REQUIRE_IO_THREAD(); + static const int64 max_size = 1024 * 1024 * 20; // 20mb. // Grant the quota request if the size is reasonable. @@ -533,6 +560,8 @@ bool ClientHandler::OnQuotaRequest(CefRefPtr browser, void ClientHandler::OnProtocolExecution(CefRefPtr browser, const CefString& url, bool& allow_os_execution) { + CEF_REQUIRE_UI_THREAD(); + std::string urlStr = url; // Allow OS execution of Spotify URIs. @@ -542,6 +571,8 @@ void ClientHandler::OnProtocolExecution(CefRefPtr browser, void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) { + CEF_REQUIRE_UI_THREAD(); + message_router_->OnRenderProcessTerminated(browser); // Load the startup URL if that's not the website that we terminated on. @@ -557,13 +588,15 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser, } bool ClientHandler::GetRootScreenRect(CefRefPtr browser, - CefRect& rect) { + CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return false; return osr_handler_->GetRootScreenRect(browser, rect); } bool ClientHandler::GetViewRect(CefRefPtr browser, CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return false; return osr_handler_->GetViewRect(browser, rect); @@ -574,6 +607,7 @@ bool ClientHandler::GetScreenPoint(CefRefPtr browser, int viewY, int& screenX, int& screenY) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return false; return osr_handler_->GetScreenPoint(browser, viewX, viewY, screenX, screenY); @@ -581,6 +615,7 @@ bool ClientHandler::GetScreenPoint(CefRefPtr browser, bool ClientHandler::GetScreenInfo(CefRefPtr browser, CefScreenInfo& screen_info) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return false; return osr_handler_->GetScreenInfo(browser, screen_info); @@ -588,6 +623,7 @@ bool ClientHandler::GetScreenInfo(CefRefPtr browser, void ClientHandler::OnPopupShow(CefRefPtr browser, bool show) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return; return osr_handler_->OnPopupShow(browser, show); @@ -595,6 +631,7 @@ void ClientHandler::OnPopupShow(CefRefPtr browser, void ClientHandler::OnPopupSize(CefRefPtr browser, const CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return; return osr_handler_->OnPopupSize(browser, rect); @@ -606,6 +643,7 @@ void ClientHandler::OnPaint(CefRefPtr browser, const void* buffer, int width, int height) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return; osr_handler_->OnPaint(browser, type, dirtyRects, buffer, width, height); @@ -613,6 +651,7 @@ void ClientHandler::OnPaint(CefRefPtr browser, void ClientHandler::OnCursorChange(CefRefPtr browser, CefCursorHandle cursor) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return; osr_handler_->OnCursorChange(browser, cursor); @@ -622,6 +661,7 @@ bool ClientHandler::StartDragging(CefRefPtr browser, CefRefPtr drag_data, CefRenderHandler::DragOperationsMask allowed_ops, int x, int y) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return false; return osr_handler_->StartDragging(browser, drag_data, allowed_ops, x, y); @@ -629,38 +669,88 @@ bool ClientHandler::StartDragging(CefRefPtr browser, void ClientHandler::UpdateDragCursor(CefRefPtr browser, CefRenderHandler::DragOperation operation) { + CEF_REQUIRE_UI_THREAD(); if (!osr_handler_.get()) return; osr_handler_->UpdateDragCursor(browser, operation); } void ClientHandler::SetMainWindowHandle(ClientWindowHandle handle) { - AutoLock lock_scope(this); + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandler::SetMainWindowHandle, this, handle)); + return; + } + main_handle_ = handle; } +ClientWindowHandle ClientHandler::GetMainWindowHandle() const { + CEF_REQUIRE_UI_THREAD(); + return main_handle_; +} + void ClientHandler::SetEditWindowHandle(ClientWindowHandle handle) { - AutoLock lock_scope(this); + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandler::SetEditWindowHandle, this, handle)); + return; + } + edit_handle_ = handle; } void ClientHandler::SetButtonWindowHandles(ClientWindowHandle backHandle, - ClientWindowHandle forwardHandle, - ClientWindowHandle reloadHandle, - ClientWindowHandle stopHandle) { - AutoLock lock_scope(this); + ClientWindowHandle forwardHandle, + ClientWindowHandle reloadHandle, + ClientWindowHandle stopHandle) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandler::SetButtonWindowHandles, this, + backHandle, forwardHandle, reloadHandle, stopHandle)); + return; + } + back_handle_ = backHandle; forward_handle_ = forwardHandle; reload_handle_ = reloadHandle; stop_handle_ = stopHandle; } +void ClientHandler::SetOSRHandler(CefRefPtr handler) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandler::SetOSRHandler, this, handler)); + return; + } + + osr_handler_ = handler; +} + +CefRefPtr ClientHandler::GetOSRHandler() const { + CEF_REQUIRE_UI_THREAD(); + return osr_handler_; +} + +CefRefPtr ClientHandler::GetBrowser() const { + base::AutoLock lock_scope(lock_); + return browser_; +} + +int ClientHandler::GetBrowserId() const { + base::AutoLock lock_scope(lock_); + return browser_id_; +} + void ClientHandler::CloseAllBrowsers(bool force_close) { if (!CefCurrentlyOn(TID_UI)) { // Execute on the UI thread. CefPostTask(TID_UI, - NewCefRunnableMethod(this, &ClientHandler::CloseAllBrowsers, - force_close)); + base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close)); return; } @@ -677,18 +767,23 @@ void ClientHandler::CloseAllBrowsers(bool force_close) { } } -std::string ClientHandler::GetLogFile() { - AutoLock lock_scope(this); +bool ClientHandler::IsClosing() const { + base::AutoLock lock_scope(lock_); + return is_closing_; +} + +std::string ClientHandler::GetLogFile() const { + CEF_REQUIRE_UI_THREAD(); return log_file_; } void ClientHandler::SetLastDownloadFile(const std::string& fileName) { - AutoLock lock_scope(this); + CEF_REQUIRE_UI_THREAD(); last_download_file_ = fileName; } -std::string ClientHandler::GetLastDownloadFile() { - AutoLock lock_scope(this); +std::string ClientHandler::GetLastDownloadFile() const { + CEF_REQUIRE_UI_THREAD(); return last_download_file_; } @@ -707,66 +802,74 @@ void ClientHandler::CloseDevTools(CefRefPtr browser) { browser->GetHost()->CloseDevTools(); } +std::string ClientHandler::GetStartupURL() const { + return startup_url_; +} + void ClientHandler::BeginTracing() { - if (CefCurrentlyOn(TID_UI)) { - CefBeginTracing(CefString(), NULL); - } else { - CefPostTask(TID_UI, - NewCefRunnableMethod(this, &ClientHandler::BeginTracing)); + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, base::Bind(&ClientHandler::BeginTracing, this)); + return; } + + CefBeginTracing(CefString(), NULL); } void ClientHandler::EndTracing() { - if (CefCurrentlyOn(TID_UI)) { - class Client : public CefEndTracingCallback, - public CefRunFileDialogCallback { - public: - explicit Client(CefRefPtr handler) - : handler_(handler) { - RunDialog(); - } - - void RunDialog() { - static const char kDefaultFileName[] = "trace.txt"; - std::string path = handler_->GetDownloadPath(kDefaultFileName); - if (path.empty()) - path = kDefaultFileName; - - // Results in a call to OnFileDialogDismissed. - handler_->GetBrowser()->GetHost()->RunFileDialog( - FILE_DIALOG_SAVE, CefString(), path, std::vector(), - this); - } - - virtual void OnFileDialogDismissed( - CefRefPtr browser_host, - const std::vector& file_paths) OVERRIDE { - if (!file_paths.empty()) { - // File selected. Results in a call to OnEndTracingComplete. - CefEndTracing(file_paths.front(), this); - } else { - // No file selected. Discard the trace data. - CefEndTracing(CefString(), NULL); - } - } - - virtual void OnEndTracingComplete( - const CefString& tracing_file) OVERRIDE { - handler_->SetLastDownloadFile(tracing_file.ToString()); - handler_->SendNotification(NOTIFY_DOWNLOAD_COMPLETE); - } - - private: - CefRefPtr handler_; - - IMPLEMENT_REFCOUNTING(Callback); - }; - - new Client(this); - } else { - CefPostTask(TID_UI, - NewCefRunnableMethod(this, &ClientHandler::EndTracing)); + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, base::Bind(&ClientHandler::EndTracing, this)); + return; } + + class Client : public CefEndTracingCallback, + public CefRunFileDialogCallback { + public: + explicit Client(CefRefPtr handler) + : handler_(handler) { + RunDialog(); + } + + void RunDialog() { + static const char kDefaultFileName[] = "trace.txt"; + std::string path = handler_->GetDownloadPath(kDefaultFileName); + if (path.empty()) + path = kDefaultFileName; + + // Results in a call to OnFileDialogDismissed. + handler_->GetBrowser()->GetHost()->RunFileDialog( + FILE_DIALOG_SAVE, CefString(), path, std::vector(), + this); + } + + virtual void OnFileDialogDismissed( + CefRefPtr browser_host, + const std::vector& file_paths) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + if (!file_paths.empty()) { + // File selected. Results in a call to OnEndTracingComplete. + CefEndTracing(file_paths.front(), this); + } else { + // No file selected. Discard the trace data. + CefEndTracing(CefString(), NULL); + } + } + + virtual void OnEndTracingComplete( + const CefString& tracing_file) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + handler_->SetLastDownloadFile(tracing_file.ToString()); + handler_->SendNotification(NOTIFY_DOWNLOAD_COMPLETE); + } + + private: + CefRefPtr handler_; + + IMPLEMENT_REFCOUNTING(Client); + }; + + new Client(this); } bool ClientHandler::Save(const std::string& path, const std::string& data) { diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index 9b8930a0e..d975cd109 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -10,6 +10,8 @@ #include #include #include + +#include "include/base/cef_lock.h" #include "include/cef_client.h" #include "include/wrapper/cef_helpers.h" #include "include/wrapper/cef_message_router.h" @@ -245,19 +247,18 @@ class ClientHandler : public CefClient, OVERRIDE; void SetMainWindowHandle(ClientWindowHandle handle); - ClientWindowHandle GetMainWindowHandle() { return main_handle_; } + ClientWindowHandle GetMainWindowHandle() const; void SetEditWindowHandle(ClientWindowHandle handle); - void SetOSRHandler(CefRefPtr handler) { - osr_handler_ = handler; - } - CefRefPtr GetOSRHandler() { return osr_handler_; } void SetButtonWindowHandles(ClientWindowHandle backHandle, ClientWindowHandle forwardHandle, ClientWindowHandle reloadHandle, ClientWindowHandle stopHandle); - CefRefPtr GetBrowser() { return browser_; } - int GetBrowserId() { return browser_id_; } + void SetOSRHandler(CefRefPtr handler); + CefRefPtr GetOSRHandler() const; + + CefRefPtr GetBrowser() const; + int GetBrowserId() const; // Request that all existing browser windows close. void CloseAllBrowsers(bool force_close); @@ -265,12 +266,12 @@ class ClientHandler : public CefClient, // Returns true if the main browser window is currently closing. Used in // combination with DoClose() and the OS close notification to properly handle // 'onbeforeunload' JavaScript events during window close. - bool IsClosing() { return is_closing_; } + bool IsClosing() const; - std::string GetLogFile(); + std::string GetLogFile() const; void SetLastDownloadFile(const std::string& fileName); - std::string GetLastDownloadFile(); + std::string GetLastDownloadFile() const; // Send a notification to the application. Notifications should not block the // caller. @@ -285,14 +286,14 @@ class ClientHandler : public CefClient, void CloseDevTools(CefRefPtr browser); // Returns the startup URL. - std::string GetStartupURL() { return startup_url_; } + std::string GetStartupURL() const; void BeginTracing(); void EndTracing(); bool Save(const std::string& path, const std::string& data); - protected: + private: void SetLoading(bool isLoading); void SetNavState(bool canGoBack, bool canGoForward); @@ -313,31 +314,55 @@ class ClientHandler : public CefClient, // use the default temp directory. std::string GetDownloadPath(const std::string& file_name); - // The child browser window + // START THREAD SAFE MEMBERS + // The following members are thread-safe because they're initialized during + // object construction and not changed thereafter. + + // The startup URL. + std::string startup_url_; + + // True if mouse cursor change is disabled. + bool mouse_cursor_change_disabled_; + // END THREAD SAFE MEMBERS + + // Lock used to protect members accessed on multiple threads. Make it mutable + // so that it can be used from const methods. + mutable base::Lock lock_; + + // START LOCK PROTECTED MEMBERS + // The following members are accessed on multiple threads and must be + // protected by |lock_|. + + // The child browser window. CefRefPtr browser_; - // List of any popup browser windows. Only accessed on the CEF UI thread. - typedef std::list > BrowserList; - BrowserList popup_browsers_; - - // The main frame window handle - ClientWindowHandle main_handle_; - - // The child browser id + // The child browser id. int browser_id_; // True if the main browser window is currently closing. bool is_closing_; + // END LOCK PROTECTED MEMBERS - // The edit window handle + // START UI THREAD ACCESS ONLY MEMBERS + // The following members will only be accessed on the CEF UI thread. + + // List of any popup browser windows. + typedef std::list > BrowserList; + BrowserList popup_browsers_; + + // The main frame window handle. + ClientWindowHandle main_handle_; + + // The edit window handle. ClientWindowHandle edit_handle_; - // The button window handles + // The button window handles. ClientWindowHandle back_handle_; ClientWindowHandle forward_handle_; ClientWindowHandle stop_handle_; ClientWindowHandle reload_handle_; + // The handler for off-screen rendering, if any. CefRefPtr osr_handler_; // Support for logging. @@ -349,12 +374,6 @@ class ClientHandler : public CefClient, // True if an editable field currently has focus. bool focus_on_editable_field_; - // The startup URL. - std::string startup_url_; - - // True if mouse cursor change is disabled. - bool mouse_cursor_change_disabled_; - // Handles the browser side of query routing. The renderer side is handled // in client_renderer.cpp. CefRefPtr message_router_; @@ -367,17 +386,17 @@ class ClientHandler : public CefClient, static int browser_count_; #if defined(OS_LINUX) + // Linux-only implementation of GTK-based dialog boxes. static void OnDialogResponse(GtkDialog *dialog, gint response_id, ClientHandler* handler); GtkWidget* gtk_dialog_; CefRefPtr js_dialog_callback_; #endif + // END UI THREAD ACCESS ONLY MEMBERS // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(ClientHandler); - // Include the default locking implementation. - IMPLEMENT_LOCKING(ClientHandler); }; #endif // CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_H_ diff --git a/tests/cefclient/client_handler_gtk.cpp b/tests/cefclient/client_handler_gtk.cpp index 2f2990834..062a114ba 100644 --- a/tests/cefclient/client_handler_gtk.cpp +++ b/tests/cefclient/client_handler_gtk.cpp @@ -218,7 +218,7 @@ void ClientHandler::OnAddressChange(CefRefPtr browser, const CefString& url) { CEF_REQUIRE_UI_THREAD(); - if (browser_id_ == browser->GetIdentifier() && frame->IsMain()) { + if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { // Set the edit window text std::string urlStr(url); gtk_entry_set_text(GTK_ENTRY(edit_handle_), urlStr.c_str()); @@ -283,6 +283,8 @@ bool ClientHandler::OnJSDialog(CefRefPtr browser, const CefString& default_prompt_text, CefRefPtr callback, bool& suppress_message) { + CEF_REQUIRE_UI_THREAD(); + GtkButtonsType buttons = GTK_BUTTONS_NONE; GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER; std::string title; @@ -359,6 +361,8 @@ bool ClientHandler::OnBeforeUnloadDialog( const CefString& message_text, bool is_reload, CefRefPtr callback) { + CEF_REQUIRE_UI_THREAD(); + const std::string& new_message_text = message_text.ToString() + "\n\nIs it OK to leave/reload this page?"; bool suppress_message = false; @@ -368,6 +372,8 @@ bool ClientHandler::OnBeforeUnloadDialog( } void ClientHandler::OnResetDialogState(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + if (!gtk_dialog_) return; gtk_widget_destroy(gtk_dialog_); @@ -379,6 +385,8 @@ void ClientHandler::OnResetDialogState(CefRefPtr browser) { void ClientHandler::OnDialogResponse(GtkDialog* dialog, gint response_id, ClientHandler* handler) { + CEF_REQUIRE_UI_THREAD(); + DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_)); switch (response_id) { case GTK_RESPONSE_OK: @@ -400,6 +408,8 @@ void ClientHandler::SendNotification(NotificationType type) { } void ClientHandler::SetLoading(bool isLoading) { + CEF_REQUIRE_UI_THREAD(); + if (isLoading) gtk_widget_set_sensitive(GTK_WIDGET(stop_handle_), true); else @@ -407,6 +417,8 @@ void ClientHandler::SetLoading(bool isLoading) { } void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { + CEF_REQUIRE_UI_THREAD(); + if (canGoBack) gtk_widget_set_sensitive(GTK_WIDGET(back_handle_), true); else @@ -421,4 +433,3 @@ void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { std::string ClientHandler::GetDownloadPath(const std::string& file_name) { return std::string(); } - diff --git a/tests/cefclient/client_handler_mac.mm b/tests/cefclient/client_handler_mac.mm index b6c8bc7ed..1a6de49c1 100644 --- a/tests/cefclient/client_handler_mac.mm +++ b/tests/cefclient/client_handler_mac.mm @@ -14,7 +14,7 @@ void ClientHandler::OnAddressChange(CefRefPtr browser, const CefString& url) { CEF_REQUIRE_UI_THREAD(); - if (browser_id_ == browser->GetIdentifier() && frame->IsMain()) { + if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { // Set the edit window text NSTextField* textField = (NSTextField*)edit_handle_; std::string urlStr(url); diff --git a/tests/cefclient/client_handler_win.cpp b/tests/cefclient/client_handler_win.cpp index ba9f2f3b9..7b21ce526 100644 --- a/tests/cefclient/client_handler_win.cpp +++ b/tests/cefclient/client_handler_win.cpp @@ -17,7 +17,7 @@ void ClientHandler::OnAddressChange(CefRefPtr browser, const CefString& url) { CEF_REQUIRE_UI_THREAD(); - if (browser_id_ == browser->GetIdentifier() && frame->IsMain()) { + if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { // Set the edit window text SetWindowText(edit_handle_, std::wstring(url).c_str()); } @@ -29,7 +29,7 @@ void ClientHandler::OnTitleChange(CefRefPtr browser, // Set the frame window title bar CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle(); - if (browser_id_ == browser->GetIdentifier()) { + if (GetBrowserId() == browser->GetIdentifier()) { // The frame window will be the parent of the browser window hwnd = GetParent(hwnd); } diff --git a/tests/cefclient/scheme_test.cpp b/tests/cefclient/scheme_test.cpp index 4fd45bf17..773247875 100644 --- a/tests/cefclient/scheme_test.cpp +++ b/tests/cefclient/scheme_test.cpp @@ -3,8 +3,10 @@ // can be found in the LICENSE file. #include "cefclient/scheme_test.h" + #include #include + #include "include/cef_browser.h" #include "include/cef_callback.h" #include "include/cef_frame.h" @@ -36,8 +38,6 @@ class ClientSchemeHandler : public CefResourceHandler { bool handled = false; - AutoLock lock_scope(this); - std::string url = request->GetURL(); if (strstr(url.c_str(), "handler.html") != NULL) { // Build the response html @@ -110,8 +110,6 @@ class ClientSchemeHandler : public CefResourceHandler { bool has_data = false; bytes_read = 0; - AutoLock lock_scope(this); - if (offset_ < data_.length()) { // Copy the next block of data into the buffer. int transfer_size = @@ -132,7 +130,6 @@ class ClientSchemeHandler : public CefResourceHandler { size_t offset_; IMPLEMENT_REFCOUNTING(ClientSchemeHandler); - IMPLEMENT_LOCKING(ClientSchemeHandler); }; // Implementation of the factory for for creating schema handlers. diff --git a/tests/cefsimple/simple_handler.cpp b/tests/cefsimple/simple_handler.cpp index e17b7473c..0d71f0e20 100644 --- a/tests/cefsimple/simple_handler.cpp +++ b/tests/cefsimple/simple_handler.cpp @@ -7,8 +7,9 @@ #include #include +#include "include/base/cef_bind.h" #include "include/cef_app.h" -#include "include/cef_runnable.h" +#include "include/wrapper/cef_closure_task.h" #include "include/wrapper/cef_helpers.h" namespace { @@ -97,8 +98,7 @@ void SimpleHandler::CloseAllBrowsers(bool force_close) { if (!CefCurrentlyOn(TID_UI)) { // Execute on the UI thread. CefPostTask(TID_UI, - NewCefRunnableMethod(this, &SimpleHandler::CloseAllBrowsers, - force_close)); + base::Bind(&SimpleHandler::CloseAllBrowsers, this, force_close)); return; } diff --git a/tests/unittests/browser_info_map_unittest.cc b/tests/unittests/browser_info_map_unittest.cc index c53496e3c..bcb8b9655 100644 --- a/tests/unittests/browser_info_map_unittest.cc +++ b/tests/unittests/browser_info_map_unittest.cc @@ -3,8 +3,12 @@ // can be found in the LICENSE file. #include -#include "testing/gtest/include/gtest/gtest.h" + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "libcef_dll/wrapper/cef_browser_info_map.h" +#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/chromium_includes.h b/tests/unittests/chromium_includes.h new file mode 100644 index 000000000..0ed6a15a2 --- /dev/null +++ b/tests/unittests/chromium_includes.h @@ -0,0 +1,13 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef CEF_TESTS_UNITTESTS_CHROMIUM_INCLUDES_H_ +#define CEF_TESTS_UNITTESTS_CHROMIUM_INCLUDES_H_ +#pragma once + +// Include some Chromium headers first to avoid type conflicts with CEF headers. +#include "base/bind.h" +#include "base/synchronization/lock.h" + +#endif // CEF_TESTS_UNITTESTS_CHROMIUM_INCLUDES_H_ diff --git a/tests/unittests/command_line_unittest.cc b/tests/unittests/command_line_unittest.cc index 19c4b47b6..da303beb4 100644 --- a/tests/unittests/command_line_unittest.cc +++ b/tests/unittests/command_line_unittest.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_command_line.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/tests/unittests/cookie_unittest.cc b/tests/unittests/cookie_unittest.cc index 16cd0b252..9571c5307 100644 --- a/tests/unittests/cookie_unittest.cc +++ b/tests/unittests/cookie_unittest.cc @@ -3,14 +3,21 @@ // can be found in the LICENSE file. #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/files/scoped_temp_dir.h" +#include "base/synchronization/waitable_event.h" + +#include "include/base/cef_logging.h" +#include "include/base/cef_ref_counted.h" #include "include/cef_cookie.h" #include "include/cef_runnable.h" #include "include/cef_scheme.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_suite.h" -#include "base/files/scoped_temp_dir.h" -#include "base/synchronization/waitable_event.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/dialog_unittest.cc b/tests/unittests/dialog_unittest.cc index 735580ae5..6cf682149 100644 --- a/tests/unittests/dialog_unittest.cc +++ b/tests/unittests/dialog_unittest.cc @@ -2,10 +2,13 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/display_unittest.cc b/tests/unittests/display_unittest.cc index f5efec715..a1475cd45 100644 --- a/tests/unittests/display_unittest.cc +++ b/tests/unittests/display_unittest.cc @@ -3,9 +3,13 @@ // can be found in the LICENSE file. #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" -#include "tests/unittests/test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" namespace { diff --git a/tests/unittests/dom_unittest.cc b/tests/unittests/dom_unittest.cc index 26ba0d453..8a76547c3 100644 --- a/tests/unittests/dom_unittest.cc +++ b/tests/unittests/dom_unittest.cc @@ -2,10 +2,13 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_dom.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/cefclient/client_app.h" #include "tests/unittests/test_handler.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/download_unittest.cc b/tests/unittests/download_unittest.cc index 9c67eea55..771b50d6a 100644 --- a/tests/unittests/download_unittest.cc +++ b/tests/unittests/download_unittest.cc @@ -2,11 +2,15 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include "include/cef_scheme.h" +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "tests/unittests/test_handler.h" + +#include "include/cef_scheme.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" namespace { @@ -95,7 +99,7 @@ class DownloadSchemeHandler : public CefResourceHandler { std::string content_disposition_; size_t offset_; - IMPLEMENT_REFCOUNTING(SchemeHandler); + IMPLEMENT_REFCOUNTING(DownloadSchemeHandler); }; class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory { @@ -114,7 +118,7 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory { private: TrackCallback* got_download_request_; - IMPLEMENT_REFCOUNTING(SchemeHandlerFactory); + IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory); }; class DownloadTestHandler : public TestHandler { diff --git a/tests/unittests/geolocation_unittest.cc b/tests/unittests/geolocation_unittest.cc index 22c62fd70..4022c726b 100644 --- a/tests/unittests/geolocation_unittest.cc +++ b/tests/unittests/geolocation_unittest.cc @@ -2,12 +2,16 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/synchronization/waitable_event.h" + #include "include/cef_geolocation.h" #include "include/cef_runnable.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "base/synchronization/waitable_event.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/jsdialog_unittest.cc b/tests/unittests/jsdialog_unittest.cc index df5312152..75fcb1b96 100644 --- a/tests/unittests/jsdialog_unittest.cc +++ b/tests/unittests/jsdialog_unittest.cc @@ -2,9 +2,12 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" -#include "tests/unittests/test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" namespace { diff --git a/tests/unittests/life_span_unittest.cc b/tests/unittests/life_span_unittest.cc index 40931a869..c782e5721 100644 --- a/tests/unittests/life_span_unittest.cc +++ b/tests/unittests/life_span_unittest.cc @@ -2,9 +2,12 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" -#include "tests/unittests/routing_test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/routing_test_handler.h" namespace { diff --git a/tests/unittests/message_router_unittest.cc b/tests/unittests/message_router_unittest.cc index 47f19c65c..e06427ab6 100644 --- a/tests/unittests/message_router_unittest.cc +++ b/tests/unittests/message_router_unittest.cc @@ -5,13 +5,18 @@ #include #include #include -#include "base/memory/weak_ptr.h" + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "base/strings/stringprintf.h" + +#include "include/base/cef_weak_ptr.h" +#include "include/cef_v8.h" +#include "include/cef_runnable.h" #include "testing/gtest/include/gtest/gtest.h" #include "tests/unittests/routing_test_handler.h" #include "tests/cefclient/client_app.h" -#include "include/cef_v8.h" -#include "include/cef_runnable.h" // Comment out this define to disable the unit test timeout. #define TIMEOUT_ENABLED 1 diff --git a/tests/unittests/navigation_unittest.cc b/tests/unittests/navigation_unittest.cc index 558e7e9d4..86d29e20d 100644 --- a/tests/unittests/navigation_unittest.cc +++ b/tests/unittests/navigation_unittest.cc @@ -4,13 +4,17 @@ #include #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_callback.h" #include "include/cef_runnable.h" #include "include/cef_scheme.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/cefclient/client_app.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/os_rendering_unittest.cc b/tests/unittests/os_rendering_unittest.cc index 95c11c695..4af3633db 100644 --- a/tests/unittests/os_rendering_unittest.cc +++ b/tests/unittests/os_rendering_unittest.cc @@ -2,18 +2,20 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" + +#include "include/base/cef_logging.h" #include "include/cef_runnable.h" #include "include/cef_v8.h" #include "include/wrapper/cef_stream_resource_handler.h" - #include "tests/cefclient/client_app.h" #include "tests/cefclient/resource_util.h" #include "tests/unittests/routing_test_handler.h" -#include "base/logging.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/events/keycodes/keyboard_code_conversion.h" - #if defined(OS_MACOSX) #include "tests/unittests/os_rendering_unittest_mac.h" #elif defined(OS_LINUX) diff --git a/tests/unittests/os_rendering_unittest_mac.mm b/tests/unittests/os_rendering_unittest_mac.mm index 1b39bf097..75251a0df 100644 --- a/tests/unittests/os_rendering_unittest_mac.mm +++ b/tests/unittests/os_rendering_unittest_mac.mm @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #import #import diff --git a/tests/unittests/print_unittest.cc b/tests/unittests/print_unittest.cc index 56310adc4..eae9352c7 100644 --- a/tests/unittests/print_unittest.cc +++ b/tests/unittests/print_unittest.cc @@ -2,10 +2,12 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include "include/cef_print_settings.h" - #include +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_print_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/process_message_unittest.cc b/tests/unittests/process_message_unittest.cc index ecf5a0cc0..50adb351d 100644 --- a/tests/unittests/process_message_unittest.cc +++ b/tests/unittests/process_message_unittest.cc @@ -2,12 +2,15 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_process_message.h" #include "include/cef_task.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/cefclient/client_app.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/tests/unittests/request_context_unittest.cc b/tests/unittests/request_context_unittest.cc index c9a5a6bb3..005d50f1f 100644 --- a/tests/unittests/request_context_unittest.cc +++ b/tests/unittests/request_context_unittest.cc @@ -2,11 +2,14 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include "tests/unittests/test_handler.h" +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_request_context.h" #include "include/cef_request_context_handler.h" #include "include/cef_runnable.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" TEST(RequestContextTest, GetGlobalContext) { CefRefPtr context1 = diff --git a/tests/unittests/request_handler_unittest.cc b/tests/unittests/request_handler_unittest.cc index b81fed7cc..a49542b11 100644 --- a/tests/unittests/request_handler_unittest.cc +++ b/tests/unittests/request_handler_unittest.cc @@ -2,13 +2,16 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include "tests/unittests/test_handler.h" +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "base/strings/stringprintf.h" -#include "base/strings/string_number_conversions.h" + #include "include/cef_cookie.h" #include "include/cef_runnable.h" #include "testing/gtest/include/gtest/gtest.h" #include "tests/cefclient/client_app.h" +#include "tests/unittests/test_handler.h" namespace { @@ -41,7 +44,7 @@ class NetNotifyBrowserTest : public ClientApp::BrowserDelegate { } protected: - IMPLEMENT_REFCOUNTING(HistoryNavBrowserTest); + IMPLEMENT_REFCOUNTING(NetNotifyBrowserTest); }; // Browser side. diff --git a/tests/unittests/request_unittest.cc b/tests/unittests/request_unittest.cc index 91610f735..699d19e65 100644 --- a/tests/unittests/request_unittest.cc +++ b/tests/unittests/request_unittest.cc @@ -4,12 +4,15 @@ #include +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_request.h" #include "include/cef_runnable.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/cefclient/client_app.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "testing/gtest/include/gtest/gtest.h" // Verify Set/Get methods for CefRequest, CefPostData and CefPostDataElement. TEST(RequestTest, SetGet) { diff --git a/tests/unittests/routing_test_handler.cc b/tests/unittests/routing_test_handler.cc index 529f3ba1e..903a5698c 100644 --- a/tests/unittests/routing_test_handler.cc +++ b/tests/unittests/routing_test_handler.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "tests/unittests/routing_test_handler.h" #include "tests/cefclient/client_app.h" diff --git a/tests/unittests/run_all_unittests.cc b/tests/unittests/run_all_unittests.cc index c5f09f19f..26a9b7769 100644 --- a/tests/unittests/run_all_unittests.cc +++ b/tests/unittests/run_all_unittests.cc @@ -2,18 +2,18 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -// Include this first to avoid conflicts with base/cef_logging.h. -#include "base/logging.h" +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" +#include "base/threading/thread.h" + +#include "include/base/cef_bind.h" #include "include/cef_app.h" #include "include/cef_task.h" #include "include/wrapper/cef_helpers.h" #include "tests/cefclient/client_app.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_suite.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/threading/thread.h" // Include after base/bind.h to avoid name collisions with cef_tuple.h. #include "include/cef_runnable.h" diff --git a/tests/unittests/run_all_unittests_mac.mm b/tests/unittests/run_all_unittests_mac.mm index 3bec6a435..2b81f5f43 100644 --- a/tests/unittests/run_all_unittests_mac.mm +++ b/tests/unittests/run_all_unittests_mac.mm @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_app.h" #import "include/cef_application_mac.h" diff --git a/tests/unittests/scheme_handler_unittest.cc b/tests/unittests/scheme_handler_unittest.cc index cfb215066..a582c1cdc 100644 --- a/tests/unittests/scheme_handler_unittest.cc +++ b/tests/unittests/scheme_handler_unittest.cc @@ -3,6 +3,10 @@ // can be found in the LICENSE file. #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_origin_whitelist.h" #include "include/cef_callback.h" #include "include/cef_runnable.h" @@ -273,8 +277,6 @@ class ClientSchemeHandler : public CefResourceHandler { bool has_data = false; bytes_read = 0; - AutoLock lock_scope(this); - size_t size = data->size(); if (offset_ < size) { int transfer_size = @@ -301,7 +303,6 @@ class ClientSchemeHandler : public CefResourceHandler { bool has_delayed_; IMPLEMENT_REFCOUNTING(ClientSchemeHandler); - IMPLEMENT_LOCKING(ClientSchemeHandler); }; class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { diff --git a/tests/unittests/stream_resource_handler_unittest.cc b/tests/unittests/stream_resource_handler_unittest.cc index 3b2143b23..fd78f8417 100644 --- a/tests/unittests/stream_resource_handler_unittest.cc +++ b/tests/unittests/stream_resource_handler_unittest.cc @@ -5,6 +5,10 @@ #include #include #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" #include "include/cef_stream.h" #include "include/wrapper/cef_stream_resource_handler.h" @@ -88,7 +92,7 @@ class ReadHandler : public CefReadHandler { size_t offset_; int expected_result_; - IMPLEMENT_REFCOUNTING(StreamReader); + IMPLEMENT_REFCOUNTING(ReadHandler); }; class ReadTestHandler : public RoutingTestHandler { diff --git a/tests/unittests/stream_unittest.cc b/tests/unittests/stream_unittest.cc index d65409f87..15062404d 100644 --- a/tests/unittests/stream_unittest.cc +++ b/tests/unittests/stream_unittest.cc @@ -3,6 +3,10 @@ // can be found in the LICENSE file. #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_stream.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/tests/unittests/string_unittest.cc b/tests/unittests/string_unittest.cc index 60f88e33a..54bc70dea 100644 --- a/tests/unittests/string_unittest.cc +++ b/tests/unittests/string_unittest.cc @@ -4,6 +4,10 @@ #include #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/internal/cef_string.h" #include "include/internal/cef_string_list.h" #include "include/internal/cef_string_map.h" diff --git a/tests/unittests/task_unittest.cc b/tests/unittests/task_unittest.cc index 6aa84e367..aaa0738a7 100644 --- a/tests/unittests/task_unittest.cc +++ b/tests/unittests/task_unittest.cc @@ -2,10 +2,13 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" #include "include/cef_task.h" -#include "tests/unittests/test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" namespace { diff --git a/tests/unittests/test_handler.cc b/tests/unittests/test_handler.cc index e440f5b40..8713f2c11 100644 --- a/tests/unittests/test_handler.cc +++ b/tests/unittests/test_handler.cc @@ -2,7 +2,11 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "tests/unittests/test_handler.h" + #include "include/cef_command_line.h" #include "include/cef_runnable.h" #include "include/cef_stream.h" diff --git a/tests/unittests/test_handler.h b/tests/unittests/test_handler.h index fa4fc008e..fd4066b7e 100644 --- a/tests/unittests/test_handler.h +++ b/tests/unittests/test_handler.h @@ -11,11 +11,12 @@ #include #include +#include "base/synchronization/waitable_event.h" + #include "include/cef_browser.h" #include "include/cef_client.h" #include "include/cef_frame.h" #include "include/cef_task.h" -#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" class TrackCallback { @@ -224,11 +225,13 @@ class TestHandler : public CefClient, // If true test completion will be signaled when all browsers have closed. bool signal_completion_when_all_browsers_close_; + // Used to track the number of currently existing browser windows. + static int browser_count_; + // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(TestHandler); - // Used to track the number of currently existing browser windows. - static int browser_count_; + DISALLOW_COPY_AND_ASSIGN(TestHandler); }; diff --git a/tests/unittests/test_suite.cc b/tests/unittests/test_suite.cc index d10cc0682..8e8e025ca 100644 --- a/tests/unittests/test_suite.cc +++ b/tests/unittests/test_suite.cc @@ -2,8 +2,11 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "tests/unittests/test_suite.h" -#include "tests/cefclient/client_switches.h" + #include "base/command_line.h" #include "base/logging.h" #include "base/test/test_suite.h" @@ -16,6 +19,8 @@ #include "base/test/test_timeouts.h" #endif +#include "tests/cefclient/client_switches.h" + CommandLine* CefTestSuite::commandline_ = NULL; CefTestSuite::CefTestSuite(int argc, char** argv) diff --git a/tests/unittests/test_util.cc b/tests/unittests/test_util.cc index 1ac25a632..3b8111582 100644 --- a/tests/unittests/test_util.cc +++ b/tests/unittests/test_util.cc @@ -2,6 +2,8 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" #include "tests/unittests/test_util.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/tests/unittests/tracing_unittest.cc b/tests/unittests/tracing_unittest.cc index 1b298af24..83cbb5945 100644 --- a/tests/unittests/tracing_unittest.cc +++ b/tests/unittests/tracing_unittest.cc @@ -2,14 +2,18 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "base/file_util.h" #include "base/synchronization/waitable_event.h" + #include "include/cef_runnable.h" #include "include/cef_task.h" #include "include/cef_trace.h" #include "include/base/cef_trace_event.h" -#include "tests/unittests/test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" enum TracingTestType { TT_TRACE_EVENT0, diff --git a/tests/unittests/url_unittest.cc b/tests/unittests/url_unittest.cc index 621a9e394..f902c65a4 100644 --- a/tests/unittests/url_unittest.cc +++ b/tests/unittests/url_unittest.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_url.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/tests/unittests/urlrequest_unittest.cc b/tests/unittests/urlrequest_unittest.cc index 1cafbd17c..d2717ef76 100644 --- a/tests/unittests/urlrequest_unittest.cc +++ b/tests/unittests/urlrequest_unittest.cc @@ -5,20 +5,22 @@ #include #include -#include "include/cef_scheme.h" -#include "include/cef_task.h" -#include "include/cef_urlrequest.h" -#include "tests/cefclient/client_app.h" -#include "tests/unittests/test_handler.h" -#include "tests/unittests/test_util.h" +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" -#include "base/bind.h" -#include "base/callback.h" #include "base/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" + +#include "include/base/cef_bind.h" +#include "include/cef_scheme.h" +#include "include/cef_task.h" +#include "include/cef_urlrequest.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/cefclient/client_app.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_util.h" // Include after base/bind.h to avoid name collisions with cef_tuple.h. #include "include/cef_runnable.h" @@ -286,7 +288,7 @@ class RequestSchemeHandler : public CefResourceHandler { RequestRunSettings settings_; size_t offset_; - IMPLEMENT_REFCOUNTING(ClientSchemeHandler); + IMPLEMENT_REFCOUNTING(RequestSchemeHandler); }; // Serves redirect request responses. @@ -343,7 +345,7 @@ class RequestRedirectSchemeHandler : public CefResourceHandler { CefRefPtr request_; CefRefPtr response_; - IMPLEMENT_REFCOUNTING(ClientSchemeHandler); + IMPLEMENT_REFCOUNTING(RequestRedirectSchemeHandler); }; @@ -410,7 +412,7 @@ class RequestSchemeHandlerFactory : public CefSchemeHandlerFactory { RedirectHandlerMap; RedirectHandlerMap redirect_handler_map_; - IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); + IMPLEMENT_REFCOUNTING(RequestSchemeHandlerFactory); }; @@ -897,7 +899,7 @@ class RequestRendererTest : public ClientApp::RenderDelegate, RequestTestRunner test_runner_; - IMPLEMENT_REFCOUNTING(SendRecvRendererTest); + IMPLEMENT_REFCOUNTING(RequestRendererTest); }; // Browser side. @@ -1178,5 +1180,5 @@ TEST(URLRequestTest, BrowserInvalidURL) { client->RunTest(); // Verify that there's only one reference to the client. - EXPECT_EQ(1, client->GetRefCt()); + EXPECT_TRUE(client->HasOneRef()); } diff --git a/tests/unittests/v8_unittest.cc b/tests/unittests/v8_unittest.cc index 0544fd0d1..bddfd250c 100644 --- a/tests/unittests/v8_unittest.cc +++ b/tests/unittests/v8_unittest.cc @@ -3,12 +3,16 @@ // can be found in the LICENSE file. #include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_runnable.h" #include "include/cef_task.h" #include "include/cef_v8.h" #include "tests/cefclient/client_app.h" -#include "tests/unittests/test_handler.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" // How to add a new test: // 1. Add a new value to the V8TestMode enumeration. diff --git a/tests/unittests/values_unittest.cc b/tests/unittests/values_unittest.cc index 46ec3dc91..4ddd99119 100644 --- a/tests/unittests/values_unittest.cc +++ b/tests/unittests/values_unittest.cc @@ -2,12 +2,14 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_task.h" #include "include/cef_values.h" +#include "testing/gtest/include/gtest/gtest.h" #include "tests/unittests/test_handler.h" #include "tests/unittests/test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - namespace { diff --git a/tests/unittests/version_unittest.cc b/tests/unittests/version_unittest.cc index adc84200a..b4d5f3016 100644 --- a/tests/unittests/version_unittest.cc +++ b/tests/unittests/version_unittest.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_version.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/tests/unittests/xml_reader_unittest.cc b/tests/unittests/xml_reader_unittest.cc index fcc85600e..aa7f8b730 100644 --- a/tests/unittests/xml_reader_unittest.cc +++ b/tests/unittests/xml_reader_unittest.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_stream.h" #include "include/cef_xml_reader.h" #include "include/wrapper/cef_xml_object.h" diff --git a/tests/unittests/zip_reader_unittest.cc b/tests/unittests/zip_reader_unittest.cc index 3ecb789e9..4ae10b8cc 100644 --- a/tests/unittests/zip_reader_unittest.cc +++ b/tests/unittests/zip_reader_unittest.cc @@ -2,6 +2,9 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + #include "include/cef_stream.h" #include "include/cef_zip_reader.h" #include "include/wrapper/cef_zip_archive.h" diff --git a/tools/make_cpptoc_impl.py b/tools/make_cpptoc_impl.py index 442f8270d..7d7f0aedb 100644 --- a/tools/make_cpptoc_impl.py +++ b/tools/make_cpptoc_impl.py @@ -379,7 +379,7 @@ def make_cpptoc_function_impl_new(name, func, defined_names): result += '\n#ifndef NDEBUG'\ '\n // Check that all wrapper objects have been destroyed' for name in names: - result += '\n DCHECK_EQ('+name+'::DebugObjCt, 0);'; + result += '\n DCHECK(base::AtomicRefCountIsZero(&'+name+'::DebugObjCt));'; result += '\n#endif // !NDEBUG' if len(result) != result_len: @@ -479,7 +479,7 @@ def make_cpptoc_class_impl(header, clsname, impl): const += '}\n\n'+ \ '#ifndef NDEBUG\n'+ \ - 'template<> long CefCppToC<'+clsname+'CppToC, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ + 'template<> base::AtomicRefCount CefCppToC<'+clsname+'CppToC, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ '#endif\n' result += wrap_code(const) diff --git a/tools/make_ctocpp_impl.py b/tools/make_ctocpp_impl.py index 197ea6d77..1d109fb7c 100644 --- a/tools/make_ctocpp_impl.py +++ b/tools/make_ctocpp_impl.py @@ -414,7 +414,7 @@ def make_ctocpp_function_impl_new(clsname, name, func): result += '\n#ifndef NDEBUG'\ '\n // Check that all wrapper objects have been destroyed' for name in names: - result += '\n DCHECK_EQ('+name+'::DebugObjCt, 0);'; + result += '\n DCHECK(base::AtomicRefCountIsZero(&'+name+'::DebugObjCt));'; result += '\n#endif // !NDEBUG' if len(result) != result_len: @@ -496,7 +496,7 @@ def make_ctocpp_class_impl(header, clsname, impl): result += includes+'\n'+resultingimpl+'\n' result += wrap_code('#ifndef NDEBUG\n'+ \ - 'template<> long CefCToCpp<'+clsname+'CToCpp, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ + 'template<> base::AtomicRefCount CefCToCpp<'+clsname+'CToCpp, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ '#endif\n') return result