mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-09 05:12:38 +00:00
Support for Signal calls.
Merge in RedPhone // FREEBIE
This commit is contained in:
228
jni/webrtc/system_wrappers/BUILD.gn
Normal file
228
jni/webrtc/system_wrappers/BUILD.gn
Normal file
@@ -0,0 +1,228 @@
|
||||
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("//build/config/android/config.gni")
|
||||
import("../build/webrtc.gni")
|
||||
|
||||
config("system_wrappers_inherited_config") {
|
||||
include_dirs = [
|
||||
"interface",
|
||||
]
|
||||
}
|
||||
|
||||
static_library("system_wrappers") {
|
||||
sources = [
|
||||
"interface/aligned_malloc.h",
|
||||
"interface/atomic32.h",
|
||||
"interface/clock.h",
|
||||
"interface/compile_assert.h",
|
||||
"interface/condition_variable_wrapper.h",
|
||||
"interface/cpu_info.h",
|
||||
"interface/cpu_features_wrapper.h",
|
||||
"interface/critical_section_wrapper.h",
|
||||
"interface/data_log.h",
|
||||
"interface/data_log_c.h",
|
||||
"interface/data_log_impl.h",
|
||||
"interface/event_tracer.h",
|
||||
"interface/event_wrapper.h",
|
||||
"interface/field_trial.h",
|
||||
"interface/file_wrapper.h",
|
||||
"interface/fix_interlocked_exchange_pointer_win.h",
|
||||
"interface/logging.h",
|
||||
"interface/ref_count.h",
|
||||
"interface/rtp_to_ntp.h",
|
||||
"interface/rw_lock_wrapper.h",
|
||||
"interface/scoped_ptr.h",
|
||||
"interface/scoped_refptr.h",
|
||||
"interface/scoped_vector.h",
|
||||
"interface/sleep.h",
|
||||
"interface/sort.h",
|
||||
"interface/static_instance.h",
|
||||
"interface/stl_util.h",
|
||||
"interface/stringize_macros.h",
|
||||
"interface/thread_annotations.h",
|
||||
"interface/thread_wrapper.h",
|
||||
"interface/tick_util.h",
|
||||
"interface/timestamp_extrapolator.h",
|
||||
"interface/trace.h",
|
||||
"interface/trace_event.h",
|
||||
"interface/utf_util_win.h",
|
||||
"source/aligned_malloc.cc",
|
||||
"source/atomic32_mac.cc",
|
||||
"source/atomic32_win.cc",
|
||||
"source/clock.cc",
|
||||
"source/condition_variable.cc",
|
||||
"source/condition_variable_posix.cc",
|
||||
"source/condition_variable_posix.h",
|
||||
"source/condition_variable_event_win.cc",
|
||||
"source/condition_variable_event_win.h",
|
||||
"source/condition_variable_native_win.cc",
|
||||
"source/condition_variable_native_win.h",
|
||||
"source/cpu_info.cc",
|
||||
"source/cpu_features.cc",
|
||||
"source/critical_section.cc",
|
||||
"source/critical_section_posix.cc",
|
||||
"source/critical_section_posix.h",
|
||||
"source/critical_section_win.cc",
|
||||
"source/critical_section_win.h",
|
||||
"source/data_log_c.cc",
|
||||
"source/event.cc",
|
||||
"source/event_posix.cc",
|
||||
"source/event_posix.h",
|
||||
"source/event_tracer.cc",
|
||||
"source/event_win.cc",
|
||||
"source/event_win.h",
|
||||
"source/file_impl.cc",
|
||||
"source/file_impl.h",
|
||||
"source/logging.cc",
|
||||
"source/rtp_to_ntp.cc",
|
||||
"source/rw_lock.cc",
|
||||
"source/rw_lock_generic.cc",
|
||||
"source/rw_lock_generic.h",
|
||||
"source/rw_lock_posix.cc",
|
||||
"source/rw_lock_posix.h",
|
||||
"source/rw_lock_win.cc",
|
||||
"source/rw_lock_win.h",
|
||||
"source/set_thread_name_win.h",
|
||||
"source/sleep.cc",
|
||||
"source/sort.cc",
|
||||
"source/tick_util.cc",
|
||||
"source/thread.cc",
|
||||
"source/thread_posix.cc",
|
||||
"source/thread_posix.h",
|
||||
"source/thread_win.cc",
|
||||
"source/thread_win.h",
|
||||
"source/timestamp_extrapolator.cc",
|
||||
"source/trace_impl.cc",
|
||||
"source/trace_impl.h",
|
||||
"source/trace_posix.cc",
|
||||
"source/trace_posix.h",
|
||||
"source/trace_win.cc",
|
||||
"source/trace_win.h",
|
||||
]
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
|
||||
direct_dependent_configs = [
|
||||
"..:common_inherited_config",
|
||||
":system_wrappers_inherited_config",
|
||||
]
|
||||
|
||||
if (enable_data_logging) {
|
||||
sources += [ "source/data_log.cc" ]
|
||||
} else {
|
||||
sources += [ "source/data_log_no_op.cc" ]
|
||||
}
|
||||
|
||||
defines = []
|
||||
libs = []
|
||||
deps = []
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"interface/logcat_trace_context.h",
|
||||
"source/logcat_trace_context.cc",
|
||||
]
|
||||
|
||||
defines += [
|
||||
"WEBRTC_THREAD_RR",
|
||||
# TODO(leozwang): Investigate CLOCK_REALTIME and CLOCK_MONOTONIC
|
||||
# support on Android. Keep WEBRTC_CLOCK_TYPE_REALTIME for now,
|
||||
# remove it after I verify that CLOCK_MONOTONIC is fully functional
|
||||
# with condition and event functions in system_wrappers.
|
||||
"WEBRTC_CLOCK_TYPE_REALTIME",
|
||||
]
|
||||
|
||||
deps += [ ":cpu_features_android" ]
|
||||
|
||||
libs += [ "log" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
defines += [
|
||||
"WEBRTC_THREAD_RR",
|
||||
# TODO(andrew): can we select this automatically?
|
||||
# Define this if the Linux system does not support CLOCK_MONOTONIC.
|
||||
#"WEBRTC_CLOCK_TYPE_REALTIME",
|
||||
]
|
||||
|
||||
libs += [ "rt" ]
|
||||
}
|
||||
|
||||
if (!is_mac && !is_ios) {
|
||||
sources += [
|
||||
"source/atomic32_posix.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios || is_mac) {
|
||||
defines += [
|
||||
"WEBRTC_THREAD_RR",
|
||||
"WEBRTC_CLOCK_TYPE_REALTIME",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
sources += [
|
||||
"source/atomic32_mac.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
libs += [ "winmm.lib" ]
|
||||
|
||||
cflags = [
|
||||
"/wd4267", # size_t to int truncation.
|
||||
"/wd4334", # Ignore warning on shift operator promotion.
|
||||
]
|
||||
}
|
||||
|
||||
include_dirs = [
|
||||
"source/spreadsortlib",
|
||||
]
|
||||
|
||||
deps += [
|
||||
"../base:webrtc_base",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("field_trial_default") {
|
||||
sources = [
|
||||
"source/field_trial_default.cc",
|
||||
]
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
source_set("cpu_features_android") {
|
||||
sources = [
|
||||
"source/cpu_features_android.c",
|
||||
]
|
||||
|
||||
if (is_android_webview_build) {
|
||||
libs += [ "cpufeatures.a" ]
|
||||
} else {
|
||||
deps = [ "//third_party/android_tools:cpu_features" ]
|
||||
}
|
||||
}
|
||||
}
|
8
jni/webrtc/system_wrappers/OWNERS
Normal file
8
jni/webrtc/system_wrappers/OWNERS
Normal file
@@ -0,0 +1,8 @@
|
||||
henrike@webrtc.org
|
||||
perkj@webrtc.org
|
||||
henrika@webrtc.org
|
||||
henrikg@webrtc.org
|
||||
mflodman@webrtc.org
|
||||
niklas.enbom@webrtc.org
|
||||
|
||||
per-file BUILD.gn=kjellander@webrtc.org
|
59
jni/webrtc/system_wrappers/interface/aligned_malloc.h
Normal file
59
jni/webrtc/system_wrappers/interface/aligned_malloc.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
|
||||
// The functions declared here
|
||||
// 1) Allocates block of aligned memory.
|
||||
// 2) Re-calculates a pointer such that it is aligned to a higher or equal
|
||||
// address.
|
||||
// Note: alignment must be a power of two. The alignment is in bytes.
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Returns a pointer to the first boundry of |alignment| bytes following the
|
||||
// address of |ptr|.
|
||||
// Note that there is no guarantee that the memory in question is available.
|
||||
// |ptr| has no requirements other than it can't be NULL.
|
||||
void* GetRightAlign(const void* ptr, size_t alignment);
|
||||
|
||||
// Allocates memory of |size| bytes aligned on an |alignment| boundry.
|
||||
// The return value is a pointer to the memory. Note that the memory must
|
||||
// be de-allocated using AlignedFree.
|
||||
void* AlignedMalloc(size_t size, size_t alignment);
|
||||
// De-allocates memory created using the AlignedMalloc() API.
|
||||
void AlignedFree(void* mem_block);
|
||||
|
||||
// Templated versions to facilitate usage of aligned malloc without casting
|
||||
// to and from void*.
|
||||
template<typename T>
|
||||
T* GetRightAlign(const T* ptr, size_t alignment) {
|
||||
return reinterpret_cast<T*>(GetRightAlign(reinterpret_cast<const void*>(ptr),
|
||||
alignment));
|
||||
}
|
||||
template<typename T>
|
||||
T* AlignedMalloc(size_t size, size_t alignment) {
|
||||
return reinterpret_cast<T*>(AlignedMalloc(size, alignment));
|
||||
}
|
||||
|
||||
// Deleter for use with scoped_ptr. E.g., use as
|
||||
// scoped_ptr<Foo, AlignedFreeDeleter> foo;
|
||||
struct AlignedFreeDeleter {
|
||||
inline void operator()(void* ptr) const {
|
||||
AlignedFree(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
59
jni/webrtc/system_wrappers/interface/asm_defines.h
Normal file
59
jni/webrtc/system_wrappers/interface/asm_defines.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ASM_DEFINES_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ASM_DEFINES_H_
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
// Define the macros used in ARM assembly code, so that for Mac or iOS builds
|
||||
// we add leading underscores for the function names.
|
||||
#ifdef __APPLE__
|
||||
.macro GLOBAL_FUNCTION name
|
||||
.global _\name
|
||||
.endm
|
||||
.macro DEFINE_FUNCTION name
|
||||
_\name:
|
||||
.endm
|
||||
.macro CALL_FUNCTION name
|
||||
bl _\name
|
||||
.endm
|
||||
.macro GLOBAL_LABEL name
|
||||
.global _\name
|
||||
.endm
|
||||
#else
|
||||
.macro GLOBAL_FUNCTION name
|
||||
.global \name
|
||||
.endm
|
||||
.macro DEFINE_FUNCTION name
|
||||
\name:
|
||||
.endm
|
||||
.macro CALL_FUNCTION name
|
||||
bl \name
|
||||
.endm
|
||||
.macro GLOBAL_LABEL name
|
||||
.global \name
|
||||
.endm
|
||||
#endif
|
||||
|
||||
// With Apple's clang compiler, for instructions ldrb, strh, etc.,
|
||||
// the condition code is after the width specifier. Here we define
|
||||
// only the ones that are actually used in the assembly files.
|
||||
#if (defined __llvm__) && (defined __APPLE__)
|
||||
.macro streqh reg1, reg2, num
|
||||
strheq \reg1, \reg2, \num
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ASM_DEFINES_H_
|
66
jni/webrtc/system_wrappers/interface/atomic32.h
Normal file
66
jni/webrtc/system_wrappers/interface/atomic32.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Atomic, system independent 32-bit integer. Unless you know what you're
|
||||
// doing, use locks instead! :-)
|
||||
//
|
||||
// Note: assumes 32-bit (or higher) system
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// 32 bit atomic variable. Note that this class relies on the compiler to
|
||||
// align the 32 bit value correctly (on a 32 bit boundary), so as long as you're
|
||||
// not doing things like reinterpret_cast over some custom allocated memory
|
||||
// without being careful with alignment, you should be fine.
|
||||
class Atomic32 {
|
||||
public:
|
||||
Atomic32(int32_t initial_value = 0);
|
||||
~Atomic32();
|
||||
|
||||
// Prefix operator!
|
||||
int32_t operator++();
|
||||
int32_t operator--();
|
||||
|
||||
int32_t operator+=(int32_t value);
|
||||
int32_t operator-=(int32_t value);
|
||||
|
||||
// Sets the value atomically to new_value if the value equals compare value.
|
||||
// The function returns true if the exchange happened.
|
||||
bool CompareExchange(int32_t new_value, int32_t compare_value);
|
||||
int32_t Value() {
|
||||
return *this += 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable the + and - operator since it's unclear what these operations
|
||||
// should do.
|
||||
Atomic32 operator+(const Atomic32& other);
|
||||
Atomic32 operator-(const Atomic32& other);
|
||||
|
||||
// Checks if |_value| is 32bit aligned.
|
||||
inline bool Is32bitAligned() const {
|
||||
return (reinterpret_cast<ptrdiff_t>(&value_) & 3) == 0;
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Atomic32);
|
||||
|
||||
int32_t value_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
|
85
jni/webrtc/system_wrappers/interface/clock.h
Normal file
85
jni/webrtc/system_wrappers/interface/clock.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CLOCK_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CLOCK_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// January 1970, in NTP seconds.
|
||||
const uint32_t kNtpJan1970 = 2208988800UL;
|
||||
|
||||
// Magic NTP fractional unit.
|
||||
const double kMagicNtpFractionalUnit = 4.294967296E+9;
|
||||
|
||||
// A clock interface that allows reading of absolute and relative timestamps.
|
||||
class Clock {
|
||||
public:
|
||||
virtual ~Clock() {}
|
||||
|
||||
// Return a timestamp in milliseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMilliseconds() const = 0;
|
||||
|
||||
// Return a timestamp in microseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMicroseconds() const = 0;
|
||||
|
||||
// Retrieve an NTP absolute timestamp in seconds and fractions of a second.
|
||||
virtual void CurrentNtp(uint32_t& seconds, uint32_t& fractions) const = 0;
|
||||
|
||||
// Retrieve an NTP absolute timestamp in milliseconds.
|
||||
virtual int64_t CurrentNtpInMilliseconds() const = 0;
|
||||
|
||||
// Converts an NTP timestamp to a millisecond timestamp.
|
||||
static int64_t NtpToMs(uint32_t seconds, uint32_t fractions);
|
||||
|
||||
// Returns an instance of the real-time system clock implementation.
|
||||
static Clock* GetRealTimeClock();
|
||||
};
|
||||
|
||||
class SimulatedClock : public Clock {
|
||||
public:
|
||||
explicit SimulatedClock(int64_t initial_time_us);
|
||||
|
||||
virtual ~SimulatedClock();
|
||||
|
||||
// Return a timestamp in milliseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMilliseconds() const OVERRIDE;
|
||||
|
||||
// Return a timestamp in microseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMicroseconds() const OVERRIDE;
|
||||
|
||||
// Retrieve an NTP absolute timestamp in milliseconds.
|
||||
virtual void CurrentNtp(uint32_t& seconds,
|
||||
uint32_t& fractions) const OVERRIDE;
|
||||
|
||||
// Converts an NTP timestamp to a millisecond timestamp.
|
||||
virtual int64_t CurrentNtpInMilliseconds() const OVERRIDE;
|
||||
|
||||
// Advance the simulated clock with a given number of milliseconds or
|
||||
// microseconds.
|
||||
void AdvanceTimeMilliseconds(int64_t milliseconds);
|
||||
void AdvanceTimeMicroseconds(int64_t microseconds);
|
||||
|
||||
private:
|
||||
int64_t time_us_;
|
||||
scoped_ptr<RWLockWrapper> lock_;
|
||||
};
|
||||
|
||||
}; // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CLOCK_H_
|
90
jni/webrtc/system_wrappers/interface/compile_assert.h
Normal file
90
jni/webrtc/system_wrappers/interface/compile_assert.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/macros.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
||||
|
||||
// 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.
|
||||
|
||||
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
|
||||
// libjingle are merged.
|
||||
#if !defined(COMPILE_ASSERT)
|
||||
#if __cplusplus >= 201103L
|
||||
// Under C++11, just use static_assert.
|
||||
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
|
||||
|
||||
#else
|
||||
template <bool>
|
||||
struct CompileAssert {
|
||||
};
|
||||
|
||||
#define COMPILE_ASSERT(expr, msg) \
|
||||
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
#endif // !defined(COMPILE_ASSERT)
|
||||
|
||||
// Implementation details of COMPILE_ASSERT:
|
||||
//
|
||||
// - COMPILE_ASSERT works by defining an array type that has -1
|
||||
// elements (and thus is invalid) when the expression is false.
|
||||
//
|
||||
// - The simpler definition
|
||||
//
|
||||
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||
//
|
||||
// does not work, as gcc supports variable-length arrays whose sizes
|
||||
// are determined at run-time (this is gcc's extension and not part
|
||||
// of the C++ standard). As a result, gcc fails to reject the
|
||||
// following code with the simple definition:
|
||||
//
|
||||
// int foo;
|
||||
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
|
||||
// // not a compile-time constant.
|
||||
//
|
||||
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||
// expr is a compile-time constant. (Template arguments must be
|
||||
// determined at compile-time.)
|
||||
//
|
||||
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
|
||||
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||
//
|
||||
// CompileAssert<bool(expr)>
|
||||
//
|
||||
// instead, these compilers will refuse to compile
|
||||
//
|
||||
// COMPILE_ASSERT(5 > 0, some_message);
|
||||
//
|
||||
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||
// template argument list.)
|
||||
//
|
||||
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||
//
|
||||
// ((expr) ? 1 : -1).
|
||||
//
|
||||
// This is to avoid running into a bug in MS VC 7.1, which
|
||||
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
22
jni/webrtc/system_wrappers/interface/compile_assert_c.h
Normal file
22
jni/webrtc/system_wrappers/interface/compile_assert_c.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
||||
|
||||
// Only use this for C files. For C++, use compile_assert.h.
|
||||
//
|
||||
// Use this macro to verify at compile time that certain restrictions are met.
|
||||
// The argument is the boolean expression to evaluate.
|
||||
// Example:
|
||||
// COMPILE_ASSERT(sizeof(foo) < 128);
|
||||
#define COMPILE_ASSERT(expression) switch (0) {case 0: case expression:;}
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class ConditionVariableWrapper {
|
||||
public:
|
||||
// Factory method, constructor disabled.
|
||||
static ConditionVariableWrapper* CreateConditionVariable();
|
||||
|
||||
virtual ~ConditionVariableWrapper() {}
|
||||
|
||||
// Calling thread will atomically release crit_sect and wait until next
|
||||
// some other thread calls Wake() or WakeAll().
|
||||
virtual void SleepCS(CriticalSectionWrapper& crit_sect) = 0;
|
||||
|
||||
// Same as above but with a timeout.
|
||||
virtual bool SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) = 0;
|
||||
|
||||
// Wakes one thread calling SleepCS().
|
||||
virtual void Wake() = 0;
|
||||
|
||||
// Wakes all threads calling SleepCS().
|
||||
virtual void WakeAll() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
51
jni/webrtc/system_wrappers/interface/cpu_features_wrapper.h
Normal file
51
jni/webrtc/system_wrappers/interface/cpu_features_wrapper.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// List of features in x86.
|
||||
typedef enum {
|
||||
kSSE2,
|
||||
kSSE3
|
||||
} CPUFeature;
|
||||
|
||||
// List of features in ARM.
|
||||
enum {
|
||||
kCPUFeatureARMv7 = (1 << 0),
|
||||
kCPUFeatureVFPv3 = (1 << 1),
|
||||
kCPUFeatureNEON = (1 << 2),
|
||||
kCPUFeatureLDREXSTREX = (1 << 3)
|
||||
};
|
||||
|
||||
typedef int (*WebRtc_CPUInfo)(CPUFeature feature);
|
||||
|
||||
// Returns true if the CPU supports the feature.
|
||||
extern WebRtc_CPUInfo WebRtc_GetCPUInfo;
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
extern WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM;
|
||||
|
||||
// Return the features in an ARM device.
|
||||
// It detects the features in the hardware platform, and returns supported
|
||||
// values in the above enum definition as a bitmask.
|
||||
extern uint64_t WebRtc_GetCPUFeaturesARM(void);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
29
jni/webrtc/system_wrappers/interface/cpu_info.h
Normal file
29
jni/webrtc/system_wrappers/interface/cpu_info.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_INFO_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_INFO_H_
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuInfo {
|
||||
public:
|
||||
static uint32_t DetectNumberOfCores();
|
||||
|
||||
private:
|
||||
CpuInfo() {}
|
||||
static uint32_t number_of_cores_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_INFO_H_
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
||||
|
||||
// If the critical section is heavily contended it may be beneficial to use
|
||||
// read/write locks instead.
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_annotations.h"
|
||||
|
||||
namespace webrtc {
|
||||
class LOCKABLE CriticalSectionWrapper {
|
||||
public:
|
||||
// Factory method, constructor disabled
|
||||
static CriticalSectionWrapper* CreateCriticalSection();
|
||||
|
||||
virtual ~CriticalSectionWrapper() {}
|
||||
|
||||
// Tries to grab lock, beginning of a critical section. Will wait for the
|
||||
// lock to become available if the grab failed.
|
||||
virtual void Enter() EXCLUSIVE_LOCK_FUNCTION() = 0;
|
||||
|
||||
// Returns a grabbed lock, end of critical section.
|
||||
virtual void Leave() UNLOCK_FUNCTION() = 0;
|
||||
};
|
||||
|
||||
// RAII extension of the critical section. Prevents Enter/Leave mismatches and
|
||||
// provides more compact critical section syntax.
|
||||
class SCOPED_LOCKABLE CriticalSectionScoped {
|
||||
public:
|
||||
explicit CriticalSectionScoped(CriticalSectionWrapper* critsec)
|
||||
EXCLUSIVE_LOCK_FUNCTION(critsec)
|
||||
: ptr_crit_sec_(critsec) {
|
||||
ptr_crit_sec_->Enter();
|
||||
}
|
||||
|
||||
~CriticalSectionScoped() UNLOCK_FUNCTION() { ptr_crit_sec_->Leave(); }
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* ptr_crit_sec_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
119
jni/webrtc/system_wrappers/interface/data_log.h
Normal file
119
jni/webrtc/system_wrappers/interface/data_log.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This singleton can be used for logging data for offline processing. Data
|
||||
// logged with it can conveniently be parsed and processed with e.g. Matlab.
|
||||
//
|
||||
// Following is an example of the log file format, starting with the header
|
||||
// row at line 1, and the data rows following.
|
||||
// col1,col2,col3,multi-value-col4[3],,,col5
|
||||
// 123,10.2,-243,1,2,3,100
|
||||
// 241,12.3,233,1,2,3,200
|
||||
// 13,16.4,-13,1,2,3,300
|
||||
//
|
||||
// As can be seen in the example, a multi-value-column is specified with the
|
||||
// name followed the number of elements it contains. This followed by
|
||||
// number of elements - 1 empty columns.
|
||||
//
|
||||
// Without multi-value-columns this format can be natively by Matlab. With
|
||||
// multi-value-columns a small Matlab script is needed, available at
|
||||
// trunk/tools/matlab/parseLog.m.
|
||||
//
|
||||
// Table names and column names are case sensitive.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class DataLog {
|
||||
public:
|
||||
// Creates a log which uses a separate thread (referred to as the file
|
||||
// writer thread) for writing log rows to file.
|
||||
//
|
||||
// Calls to this function after the log object has been created will only
|
||||
// increment the reference counter.
|
||||
static int CreateLog();
|
||||
|
||||
// Decrements the reference counter and deletes the log when the counter
|
||||
// reaches 0. Should be called equal number of times as successful calls to
|
||||
// CreateLog or memory leak will occur.
|
||||
static void ReturnLog();
|
||||
|
||||
// Combines the string table_name and the integer table_id into a new string
|
||||
// table_name + _ + table_id. The new string will be lower-case.
|
||||
static std::string Combine(const std::string& table_name, int table_id);
|
||||
|
||||
// Adds a new table, with the name table_name, and creates the file, with the
|
||||
// name table_name + ".txt", to which the table will be written.
|
||||
// table_name is treated in a case sensitive way.
|
||||
static int AddTable(const std::string& table_name);
|
||||
|
||||
// Adds a new column to a table. The column will be a multi-value-column
|
||||
// if multi_value_length is greater than 1.
|
||||
// table_name and column_name are treated in a case sensitive way.
|
||||
static int AddColumn(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
int multi_value_length);
|
||||
|
||||
// Inserts a single value into a table with name table_name at the column with
|
||||
// name column_name.
|
||||
// Note that the ValueContainer makes use of the copy constructor,
|
||||
// operator= and operator<< of the type T, and that the template type must
|
||||
// implement a deep copy copy constructor and operator=.
|
||||
// Copy constructor and operator= must not be disabled for the type T.
|
||||
// table_name and column_name are treated in a case sensitive way.
|
||||
template<class T>
|
||||
static int InsertCell(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
T value) {
|
||||
DataLogImpl* data_log = DataLogImpl::StaticInstance();
|
||||
if (data_log == NULL)
|
||||
return -1;
|
||||
return data_log->InsertCell(
|
||||
table_name,
|
||||
column_name,
|
||||
new ValueContainer<T>(value));
|
||||
}
|
||||
|
||||
// Inserts an array of values into a table with name table_name at the
|
||||
// column specified by column_name, which must be a multi-value-column.
|
||||
// Note that the MultiValueContainer makes use of the copy constructor,
|
||||
// operator= and operator<< of the type T, and that the template type
|
||||
// must implement a deep copy copy constructor and operator=.
|
||||
// Copy constructor and operator= must not be disabled for the type T.
|
||||
// table_name and column_name are treated in a case sensitive way.
|
||||
template<class T>
|
||||
static int InsertCell(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
const T* array,
|
||||
int length) {
|
||||
DataLogImpl* data_log = DataLogImpl::StaticInstance();
|
||||
if (data_log == NULL)
|
||||
return -1;
|
||||
return data_log->InsertCell(
|
||||
table_name,
|
||||
column_name,
|
||||
new MultiValueContainer<T>(array, length));
|
||||
}
|
||||
|
||||
// For the table with name table_name: Writes the current row to file.
|
||||
// Starts a new empty row.
|
||||
// table_name is treated in a case-sensitive way.
|
||||
static int NextRow(const std::string& table_name);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_H_
|
85
jni/webrtc/system_wrappers/interface/data_log_c.h
Normal file
85
jni/webrtc/system_wrappers/interface/data_log_c.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This is a pure C wrapper of the DataLog class. The functions are directly
|
||||
// mapped here except for InsertCell as C does not support templates.
|
||||
// See data_log.h for a description of the functions.
|
||||
|
||||
#ifndef SRC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_C_H_
|
||||
#define SRC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_C_H_
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// All char* parameters in this file are expected to be null-terminated
|
||||
// character sequences.
|
||||
int WebRtcDataLog_CreateLog();
|
||||
void WebRtcDataLog_ReturnLog();
|
||||
char* WebRtcDataLog_Combine(char* combined_name, size_t combined_len,
|
||||
const char* table_name, int table_id);
|
||||
int WebRtcDataLog_AddTable(const char* table_name);
|
||||
int WebRtcDataLog_AddColumn(const char* table_name, const char* column_name,
|
||||
int multi_value_length);
|
||||
|
||||
int WebRtcDataLog_InsertCell_int(const char* table_name,
|
||||
const char* column_name,
|
||||
int value);
|
||||
int WebRtcDataLog_InsertArray_int(const char* table_name,
|
||||
const char* column_name,
|
||||
const int* values,
|
||||
int length);
|
||||
int WebRtcDataLog_InsertCell_float(const char* table_name,
|
||||
const char* column_name,
|
||||
float value);
|
||||
int WebRtcDataLog_InsertArray_float(const char* table_name,
|
||||
const char* column_name,
|
||||
const float* values,
|
||||
int length);
|
||||
int WebRtcDataLog_InsertCell_double(const char* table_name,
|
||||
const char* column_name,
|
||||
double value);
|
||||
int WebRtcDataLog_InsertArray_double(const char* table_name,
|
||||
const char* column_name,
|
||||
const double* values,
|
||||
int length);
|
||||
int WebRtcDataLog_InsertCell_int32(const char* table_name,
|
||||
const char* column_name,
|
||||
int32_t value);
|
||||
int WebRtcDataLog_InsertArray_int32(const char* table_name,
|
||||
const char* column_name,
|
||||
const int32_t* values,
|
||||
int length);
|
||||
int WebRtcDataLog_InsertCell_uint32(const char* table_name,
|
||||
const char* column_name,
|
||||
uint32_t value);
|
||||
int WebRtcDataLog_InsertArray_uint32(const char* table_name,
|
||||
const char* column_name,
|
||||
const uint32_t* values,
|
||||
int length);
|
||||
int WebRtcDataLog_InsertCell_int64(const char* table_name,
|
||||
const char* column_name,
|
||||
int64_t value);
|
||||
int WebRtcDataLog_InsertArray_int64(const char* table_name,
|
||||
const char* column_name,
|
||||
const int64_t* values,
|
||||
int length);
|
||||
|
||||
int WebRtcDataLog_NextRow(const char* table_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SRC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_C_H_ // NOLINT
|
155
jni/webrtc/system_wrappers/interface/data_log_impl.h
Normal file
155
jni/webrtc/system_wrappers/interface/data_log_impl.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This file contains the helper classes for the DataLog APIs. See data_log.h
|
||||
// for the APIs.
|
||||
//
|
||||
// These classes are helper classes used for logging data for offline
|
||||
// processing. Data logged with these classes can conveniently be parsed and
|
||||
// processed with e.g. Matlab.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_IMPL_H_
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class EventWrapper;
|
||||
class LogTable;
|
||||
class RWLockWrapper;
|
||||
class ThreadWrapper;
|
||||
|
||||
// All container classes need to implement a ToString-function to be
|
||||
// writable to file. Enforce this via the Container interface.
|
||||
class Container {
|
||||
public:
|
||||
virtual ~Container() {}
|
||||
|
||||
virtual void ToString(std::string* container_string) const = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ValueContainer : public Container {
|
||||
public:
|
||||
explicit ValueContainer(T data) : data_(data) {}
|
||||
|
||||
virtual void ToString(std::string* container_string) const {
|
||||
*container_string = "";
|
||||
std::stringstream ss;
|
||||
ss << data_ << ",";
|
||||
ss >> *container_string;
|
||||
}
|
||||
|
||||
private:
|
||||
T data_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MultiValueContainer : public Container {
|
||||
public:
|
||||
MultiValueContainer(const T* data, int length)
|
||||
: data_(data, data + length) {
|
||||
}
|
||||
|
||||
virtual void ToString(std::string* container_string) const {
|
||||
*container_string = "";
|
||||
std::stringstream ss;
|
||||
for (size_t i = 0; i < data_.size(); ++i)
|
||||
ss << data_[i] << ",";
|
||||
*container_string += ss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> data_;
|
||||
};
|
||||
|
||||
class DataLogImpl {
|
||||
public:
|
||||
~DataLogImpl();
|
||||
|
||||
// The implementation of the CreateLog() method declared in data_log.h.
|
||||
// See data_log.h for a description.
|
||||
static int CreateLog();
|
||||
|
||||
// The implementation of the StaticInstance() method declared in data_log.h.
|
||||
// See data_log.h for a description.
|
||||
static DataLogImpl* StaticInstance();
|
||||
|
||||
// The implementation of the ReturnLog() method declared in data_log.h. See
|
||||
// data_log.h for a description.
|
||||
static void ReturnLog();
|
||||
|
||||
// The implementation of the AddTable() method declared in data_log.h. See
|
||||
// data_log.h for a description.
|
||||
int AddTable(const std::string& table_name);
|
||||
|
||||
// The implementation of the AddColumn() method declared in data_log.h. See
|
||||
// data_log.h for a description.
|
||||
int AddColumn(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
int multi_value_length);
|
||||
|
||||
// Inserts a Container into a table with name table_name at the column
|
||||
// with name column_name.
|
||||
// column_name is treated in a case sensitive way.
|
||||
int InsertCell(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
const Container* value_container);
|
||||
|
||||
// The implementation of the NextRow() method declared in data_log.h. See
|
||||
// data_log.h for a description.
|
||||
int NextRow(const std::string& table_name);
|
||||
|
||||
private:
|
||||
DataLogImpl();
|
||||
|
||||
// Initializes the DataLogImpl object, allocates and starts the
|
||||
// thread file_writer_thread_.
|
||||
int Init();
|
||||
|
||||
// Write all complete rows in every table to file.
|
||||
// This function should only be called by the file_writer_thread_ if that
|
||||
// thread is running to avoid race conditions.
|
||||
void Flush();
|
||||
|
||||
// Run() is called by the thread file_writer_thread_.
|
||||
static bool Run(void* obj);
|
||||
|
||||
// This function writes data to file. Note, it blocks if there is no data
|
||||
// that should be written to file availble. Flush is the non-blocking
|
||||
// version of this function.
|
||||
void Process();
|
||||
|
||||
// Stops the continuous calling of Process().
|
||||
void StopThread();
|
||||
|
||||
// Collection of tables indexed by the table name as std::string.
|
||||
typedef std::map<std::string, LogTable*> TableMap;
|
||||
typedef webrtc::scoped_ptr<CriticalSectionWrapper> CritSectScopedPtr;
|
||||
|
||||
static CritSectScopedPtr crit_sect_;
|
||||
static DataLogImpl* instance_;
|
||||
int counter_;
|
||||
TableMap tables_;
|
||||
EventWrapper* flush_event_;
|
||||
ThreadWrapper* file_writer_thread_;
|
||||
RWLockWrapper* tables_lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_DATA_LOG_IMPL_H_
|
73
jni/webrtc/system_wrappers/interface/event_tracer.h
Normal file
73
jni/webrtc/system_wrappers/interface/event_tracer.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This file defines the interface for event tracing in WebRTC.
|
||||
//
|
||||
// Event log handlers are set through SetupEventTracer(). User of this API will
|
||||
// provide two function pointers to handle event tracing calls.
|
||||
//
|
||||
// * GetCategoryEnabledPtr
|
||||
// Event tracing system calls this function to determine if a particular
|
||||
// event category is enabled.
|
||||
//
|
||||
// * AddTraceEventPtr
|
||||
// Adds a tracing event. It is the user's responsibility to log the data
|
||||
// provided.
|
||||
//
|
||||
// Parameters for the above two functions are described in trace_event.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_TRACER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_TRACER_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
typedef const unsigned char* (*GetCategoryEnabledPtr)(const char* name);
|
||||
typedef void (*AddTraceEventPtr)(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
int num_args,
|
||||
const char** arg_names,
|
||||
const unsigned char* arg_types,
|
||||
const unsigned long long* arg_values,
|
||||
unsigned char flags);
|
||||
|
||||
// User of WebRTC can call this method to setup event tracing.
|
||||
//
|
||||
// This method must be called before any WebRTC methods. Functions
|
||||
// provided should be thread-safe.
|
||||
WEBRTC_DLLEXPORT void SetupEventTracer(
|
||||
GetCategoryEnabledPtr get_category_enabled_ptr,
|
||||
AddTraceEventPtr add_trace_event_ptr);
|
||||
|
||||
// This class defines interface for the event tracing system to call
|
||||
// internally. Do not call these methods directly.
|
||||
class EventTracer {
|
||||
public:
|
||||
static const unsigned char* GetCategoryEnabled(
|
||||
const char* name);
|
||||
|
||||
static void AddTraceEvent(
|
||||
char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
int num_args,
|
||||
const char** arg_names,
|
||||
const unsigned char* arg_types,
|
||||
const unsigned long long* arg_values,
|
||||
unsigned char flags);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_TRACER_H_
|
60
jni/webrtc/system_wrappers/interface/event_wrapper.h
Normal file
60
jni/webrtc/system_wrappers/interface/event_wrapper.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
enum EventTypeWrapper {
|
||||
kEventSignaled = 1,
|
||||
kEventError = 2,
|
||||
kEventTimeout = 3
|
||||
};
|
||||
|
||||
#define WEBRTC_EVENT_10_SEC 10000
|
||||
#define WEBRTC_EVENT_INFINITE 0xffffffff
|
||||
|
||||
class EventWrapper {
|
||||
public:
|
||||
// Factory method. Constructor disabled.
|
||||
static EventWrapper* Create();
|
||||
virtual ~EventWrapper() {}
|
||||
|
||||
// Releases threads who are calling Wait() and has started waiting. Please
|
||||
// note that a thread calling Wait() will not start waiting immediately.
|
||||
// assumptions to the contrary is a very common source of issues in
|
||||
// multithreaded programming.
|
||||
// Set is sticky in the sense that it will release at least one thread
|
||||
// either immediately or some time in the future.
|
||||
virtual bool Set() = 0;
|
||||
|
||||
// Prevents future Wait() calls from finishing without a new Set() call.
|
||||
virtual bool Reset() = 0;
|
||||
|
||||
// Puts the calling thread into a wait state. The thread may be released
|
||||
// by a Set() call depending on if other threads are waiting and if so on
|
||||
// timing. The thread that was released will call Reset() before leaving
|
||||
// preventing more threads from being released. If multiple threads
|
||||
// are waiting for the same Set(), only one (random) thread is guaranteed to
|
||||
// be released. It is possible that multiple (random) threads are released
|
||||
// Depending on timing.
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time) = 0;
|
||||
|
||||
// Starts a timer that will call a non-sticky version of Set() either once
|
||||
// or periodically. If the timer is periodic it ensures that there is no
|
||||
// drift over time relative to the system clock.
|
||||
virtual bool StartTimer(bool periodic, unsigned long time) = 0;
|
||||
|
||||
virtual bool StopTimer() = 0;
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
70
jni/webrtc/system_wrappers/interface/field_trial.h
Normal file
70
jni/webrtc/system_wrappers/interface/field_trial.h
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FIELD_TRIAL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FIELD_TRIAL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
// Field trials allow webrtc clients (such as Chrome) to turn on feature code
|
||||
// in binaries out in the field and gather information with that.
|
||||
//
|
||||
// WebRTC clients MUST provide an implementation of:
|
||||
//
|
||||
// std::string webrtc::field_trial::FindFullName(const std::string& trial).
|
||||
//
|
||||
// Or link with a default one provided in:
|
||||
//
|
||||
// system_wrappers/source/system_wrappers.gyp:field_trial_default
|
||||
//
|
||||
//
|
||||
// They are designed to wire up directly to chrome field trials and to speed up
|
||||
// developers by reducing the need to wire APIs to control whether a feature is
|
||||
// on/off. E.g. to experiment with a new method that could lead to a different
|
||||
// trade-off between CPU/bandwidth:
|
||||
//
|
||||
// 1 - Develop the feature with default behaviour off:
|
||||
//
|
||||
// if (FieldTrial::FindFullName("WebRTCExperimenMethod2") == "Enabled")
|
||||
// method2();
|
||||
// else
|
||||
// method1();
|
||||
//
|
||||
// 2 - Once the changes are rolled to chrome, the new code path can be
|
||||
// controlled as normal chrome field trials.
|
||||
//
|
||||
// 3 - Evaluate the new feature and clean the code paths.
|
||||
//
|
||||
// Notes:
|
||||
// - NOT every feature is a candidate to be controlled by this mechanism as
|
||||
// it may require negotation between involved parties (e.g. SDP).
|
||||
//
|
||||
// TODO(andresp): since chrome --force-fieldtrials does not marks the trial
|
||||
// as active it does not gets propaged to renderer process. For now one
|
||||
// needs to push a config with start_active:true or run a local finch
|
||||
// server.
|
||||
//
|
||||
// TODO(andresp): find out how to get bots to run tests with trials enabled.
|
||||
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
// Returns the group name chosen for the named trial, or the empty string
|
||||
// if the trial does not exists.
|
||||
//
|
||||
// Note: To keep things tidy append all the trial names with WebRTC.
|
||||
std::string FindFullName(const std::string& name);
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FIELD_TRIAL_H_
|
87
jni/webrtc/system_wrappers/interface/file_wrapper.h
Normal file
87
jni/webrtc/system_wrappers/interface/file_wrapper.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Implementation of an InStream and OutStream that can read (exclusive) or
|
||||
// write from/to a file.
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FileWrapper : public InStream, public OutStream {
|
||||
public:
|
||||
static const size_t kMaxFileNameSize = 1024;
|
||||
|
||||
// Factory method. Constructor disabled.
|
||||
static FileWrapper* Create();
|
||||
|
||||
// Returns true if a file has been opened.
|
||||
virtual bool Open() const = 0;
|
||||
|
||||
// Opens a file in read or write mode, decided by the read_only parameter.
|
||||
virtual int OpenFile(const char* file_name_utf8,
|
||||
bool read_only,
|
||||
bool loop = false,
|
||||
bool text = false) = 0;
|
||||
|
||||
// Initializes the wrapper from an existing handle. |read_only| must match in
|
||||
// the mode the file was opened in. If |manage_file| is true, the wrapper
|
||||
// takes ownership of |handle| and closes it in CloseFile().
|
||||
virtual int OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop = false) = 0;
|
||||
|
||||
virtual int CloseFile() = 0;
|
||||
|
||||
// Limits the file size to |bytes|. Writing will fail after the cap
|
||||
// is hit. Pass zero to use an unlimited size.
|
||||
virtual int SetMaxFileSize(size_t bytes) = 0;
|
||||
|
||||
// Flush any pending writes.
|
||||
virtual int Flush() = 0;
|
||||
|
||||
// Returns the opened file's name in |file_name_utf8|. Provide the size of
|
||||
// the buffer in bytes in |size|. The name will be truncated if |size| is
|
||||
// too small.
|
||||
virtual int FileName(char* file_name_utf8,
|
||||
size_t size) const = 0;
|
||||
|
||||
// Write |format| to the opened file. Arguments are taken in the same manner
|
||||
// as printf. That is, supply a format string containing text and
|
||||
// specifiers. Returns the number of characters written or -1 on error.
|
||||
virtual int WriteText(const char* format, ...) = 0;
|
||||
|
||||
// Inherited from Instream.
|
||||
// Reads |length| bytes from file to |buf|. Returns the number of bytes read
|
||||
// or -1 on error.
|
||||
virtual int Read(void* buf, int length) = 0;
|
||||
|
||||
// Inherited from OutStream.
|
||||
// Writes |length| bytes from |buf| to file. The actual writing may happen
|
||||
// some time later. Call Flush() to force a write.
|
||||
virtual bool Write(const void* buf, int length) = 0;
|
||||
|
||||
// Inherited from both Instream and OutStream.
|
||||
// Rewinds the file to the start. Only available when OpenFile() has been
|
||||
// called with |loop| == true or |readOnly| == true.
|
||||
virtual int Rewind() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Various inline functions and macros to fix compilation of 32 bit target
|
||||
// on MSVC with /Wp64 flag enabled.
|
||||
|
||||
// The original code can be found here:
|
||||
// http://src.chromium.org/svn/trunk/src/base/fix_wp64.h
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Platform SDK fixes when building with /Wp64 for a 32 bits target.
|
||||
#if !defined(_WIN64) && defined(_Wp64)
|
||||
|
||||
#ifdef InterlockedExchangePointer
|
||||
#undef InterlockedExchangePointer
|
||||
// The problem is that the macro provided for InterlockedExchangePointer() is
|
||||
// doing a (LONG) C-style cast that triggers invariably the warning C4312 when
|
||||
// building on 32 bits.
|
||||
inline void* InterlockedExchangePointer(void* volatile* target, void* value) {
|
||||
return reinterpret_cast<void*>(static_cast<LONG_PTR>(InterlockedExchange(
|
||||
reinterpret_cast<volatile LONG*>(target),
|
||||
static_cast<LONG>(reinterpret_cast<LONG_PTR>(value)))));
|
||||
}
|
||||
#endif // #ifdef InterlockedExchangePointer
|
||||
|
||||
#endif // #if !defined(_WIN64) && defined(_Wp64)
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
35
jni/webrtc/system_wrappers/interface/logcat_trace_context.h
Normal file
35
jni/webrtc/system_wrappers/interface/logcat_trace_context.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
#ifndef ANDROID
|
||||
#error This file only makes sense to include on Android!
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Scoped helper class for directing Traces to Android's logcat facility. While
|
||||
// this object lives, Trace output will be sent to logcat.
|
||||
class LogcatTraceContext : public webrtc::TraceCallback {
|
||||
public:
|
||||
LogcatTraceContext();
|
||||
virtual ~LogcatTraceContext();
|
||||
|
||||
// TraceCallback impl.
|
||||
virtual void Print(TraceLevel level, const char* message, int length);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_
|
161
jni/webrtc/system_wrappers/interface/logging.h
Normal file
161
jni/webrtc/system_wrappers/interface/logging.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This is a highly stripped-down version of libjingle's talk/base/logging.h.
|
||||
// It is a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
|
||||
// semantics to ease a transition to that format.
|
||||
|
||||
// NOTE: LS_INFO maps to a new trace level which should be reserved for
|
||||
// infrequent, non-verbose logs. The other levels below kTraceWarning have been
|
||||
// rendered essentially useless due to their verbosity. Carefully consider the
|
||||
// impact of adding a new LS_INFO log. If it will be logged at anything
|
||||
// approaching a frame or packet frequency, use LS_VERBOSE if necessary, or
|
||||
// preferably, do not log at all.
|
||||
|
||||
// LOG(...) an ostream target that can be used to send formatted
|
||||
// output to a variety of logging targets, such as debugger console, stderr,
|
||||
// file, or any StreamInterface.
|
||||
// The severity level passed as the first argument to the LOGging
|
||||
// functions is used as a filter, to limit the verbosity of the logging.
|
||||
// Static members of LogMessage documented below are used to control the
|
||||
// verbosity and target of the output.
|
||||
// There are several variations on the LOG macro which facilitate logging
|
||||
// of common error conditions, detailed below.
|
||||
|
||||
// LOG(sev) logs the given stream at severity "sev", which must be a
|
||||
// compile-time constant of the LoggingSeverity type, without the namespace
|
||||
// prefix.
|
||||
// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
|
||||
// type (basically, it just doesn't prepend the namespace).
|
||||
// LOG_F(sev) Like LOG(), but includes the name of the current function.
|
||||
|
||||
// Additional helper macros added by WebRTC:
|
||||
// LOG_API is a shortcut for API call logging. Pass in the input parameters of
|
||||
// the method. For example:
|
||||
// Foo(int bar, int baz) {
|
||||
// LOG_API2(bar, baz);
|
||||
// }
|
||||
//
|
||||
// LOG_FERR is a shortcut for logging a failed function call. For example:
|
||||
// if (!Foo(bar)) {
|
||||
// LOG_FERR1(LS_WARNING, Foo, bar);
|
||||
// }
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note that the non-standard LoggingSeverity aliases exist because they are
|
||||
// still in broad use. The meanings of the levels are:
|
||||
// LS_SENSITIVE: Information which should only be logged with the consent
|
||||
// of the user, due to privacy concerns.
|
||||
// LS_VERBOSE: This level is for data which we do not want to appear in the
|
||||
// normal debug log, but should appear in diagnostic logs.
|
||||
// LS_INFO: Chatty level used in debugging for all sorts of things, the default
|
||||
// in debug builds.
|
||||
// LS_WARNING: Something that may warrant investigation.
|
||||
// LS_ERROR: Something that should not have occurred.
|
||||
enum LoggingSeverity {
|
||||
LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR
|
||||
};
|
||||
|
||||
class LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line, LoggingSeverity sev);
|
||||
~LogMessage();
|
||||
|
||||
static bool Loggable(LoggingSeverity sev);
|
||||
std::ostream& stream() { return print_stream_; }
|
||||
|
||||
private:
|
||||
// The ostream that buffers the formatted message before output
|
||||
std::ostringstream print_stream_;
|
||||
|
||||
// The severity level of this message
|
||||
LoggingSeverity severity_;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Macros which automatically disable logging when WEBRTC_LOGGING == 0
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOG
|
||||
// The following non-obvious technique for implementation of a
|
||||
// conditional log stream was stolen from google3/base/logging.h.
|
||||
|
||||
// This class is used to explicitly ignore values in the conditional
|
||||
// logging macros. This avoids compiler warnings like "value computed
|
||||
// is not used" and "statement has no effect".
|
||||
|
||||
class LogMessageVoidify {
|
||||
public:
|
||||
LogMessageVoidify() { }
|
||||
// This has to be an operator with a precedence lower than << but
|
||||
// higher than ?:
|
||||
void operator&(std::ostream&) { }
|
||||
};
|
||||
|
||||
#if defined(WEBRTC_RESTRICT_LOGGING)
|
||||
// This should compile away logs matching the following condition.
|
||||
#define RESTRICT_LOGGING_PRECONDITION(sev) \
|
||||
sev < webrtc::LS_INFO ? (void) 0 :
|
||||
#else
|
||||
#define RESTRICT_LOGGING_PRECONDITION(sev)
|
||||
#endif
|
||||
|
||||
#define LOG_SEVERITY_PRECONDITION(sev) \
|
||||
RESTRICT_LOGGING_PRECONDITION(sev) !(webrtc::LogMessage::Loggable(sev)) \
|
||||
? (void) 0 \
|
||||
: webrtc::LogMessageVoidify() &
|
||||
|
||||
#define LOG(sev) \
|
||||
LOG_SEVERITY_PRECONDITION(webrtc::sev) \
|
||||
webrtc::LogMessage(__FILE__, __LINE__, webrtc::sev).stream()
|
||||
|
||||
// The _V version is for when a variable is passed in. It doesn't do the
|
||||
// namespace concatination.
|
||||
#define LOG_V(sev) \
|
||||
LOG_SEVERITY_PRECONDITION(sev) \
|
||||
webrtc::LogMessage(__FILE__, __LINE__, sev).stream()
|
||||
|
||||
// The _F version prefixes the message with the current function name.
|
||||
#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F)
|
||||
#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
|
||||
#else
|
||||
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
|
||||
#endif
|
||||
|
||||
#define LOG_API0() LOG_F(LS_VERBOSE)
|
||||
#define LOG_API1(v1) LOG_API0() << #v1 << "=" << v1
|
||||
#define LOG_API2(v1, v2) LOG_API1(v1) \
|
||||
<< ", " << #v2 << "=" << v2
|
||||
#define LOG_API3(v1, v2, v3) LOG_API2(v1, v2) \
|
||||
<< ", " << #v3 << "=" << v3
|
||||
|
||||
#define LOG_FERR0(sev, func) LOG(sev) << #func << " failed"
|
||||
#define LOG_FERR1(sev, func, v1) LOG_FERR0(sev, func) \
|
||||
<< ": " << #v1 << "=" << v1
|
||||
#define LOG_FERR2(sev, func, v1, v2) LOG_FERR1(sev, func, v1) \
|
||||
<< ", " << #v2 << "=" << v2
|
||||
#define LOG_FERR3(sev, func, v1, v2, v3) LOG_FERR2(sev, func, v1, v2) \
|
||||
<< ", " << #v3 << "=" << v3
|
||||
#define LOG_FERR4(sev, func, v1, v2, v3, v4) LOG_FERR3(sev, func, v1, v2, v3) \
|
||||
<< ", " << #v4 << "=" << v4
|
||||
|
||||
#endif // LOG
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
82
jni/webrtc/system_wrappers/interface/ref_count.h
Normal file
82
jni/webrtc/system_wrappers/interface/ref_count.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
|
||||
#define SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This class can be used for instantiating
|
||||
// reference counted objects.
|
||||
// int32_t AddRef() and int32_t Release().
|
||||
// Usage:
|
||||
// RefCountImpl<T>* implementation = new RefCountImpl<T>(p);
|
||||
//
|
||||
// Example:
|
||||
// class MyInterface {
|
||||
// public:
|
||||
// virtual void DoSomething() = 0;
|
||||
// virtual int32_t AddRef() = 0;
|
||||
// virtual int32_t Release() = 0:
|
||||
// private:
|
||||
// virtual ~MyInterface(){};
|
||||
// }
|
||||
// class MyImplementation : public MyInterface {
|
||||
// public:
|
||||
// virtual DoSomething() { printf("hello"); };
|
||||
// };
|
||||
// MyImplementation* CreateMyImplementation() {
|
||||
// RefCountImpl<MyImplementation>* implementation =
|
||||
// new RefCountImpl<MyImplementation>();
|
||||
// return implementation;
|
||||
// }
|
||||
|
||||
template <class T>
|
||||
class RefCountImpl : public T {
|
||||
public:
|
||||
RefCountImpl() : ref_count_(0) {}
|
||||
|
||||
template<typename P>
|
||||
explicit RefCountImpl(P p) : T(p), ref_count_(0) {}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
RefCountImpl(P1 p1, P2 p2) : T(p1, p2), ref_count_(0) {}
|
||||
|
||||
template<typename P1, typename P2, typename P3>
|
||||
RefCountImpl(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3), ref_count_(0) {}
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4>
|
||||
RefCountImpl(P1 p1, P2 p2, P3 p3, P4 p4) : T(p1, p2, p3, p4), ref_count_(0) {}
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
RefCountImpl(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
|
||||
: T(p1, p2, p3, p4, p5), ref_count_(0) {}
|
||||
|
||||
virtual int32_t AddRef() {
|
||||
return ++ref_count_;
|
||||
}
|
||||
|
||||
virtual int32_t Release() {
|
||||
int32_t ref_count;
|
||||
ref_count = --ref_count_;
|
||||
if (ref_count == 0)
|
||||
delete this;
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
protected:
|
||||
Atomic32 ref_count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
|
50
jni/webrtc/system_wrappers/interface/rtp_to_ntp.h
Normal file
50
jni/webrtc/system_wrappers/interface/rtp_to_ntp.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INTERFACE_RTP_TO_NTP_H_
|
||||
#define SYSTEM_WRAPPERS_INTERFACE_RTP_TO_NTP_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct RtcpMeasurement {
|
||||
RtcpMeasurement();
|
||||
RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp);
|
||||
uint32_t ntp_secs;
|
||||
uint32_t ntp_frac;
|
||||
uint32_t rtp_timestamp;
|
||||
};
|
||||
|
||||
typedef std::list<RtcpMeasurement> RtcpList;
|
||||
|
||||
// Updates |rtcp_list| with timestamps from the latest RTCP SR.
|
||||
// |new_rtcp_sr| will be set to true if these are the timestamps which have
|
||||
// never be added to |rtcp_list|.
|
||||
bool UpdateRtcpList(uint32_t ntp_secs,
|
||||
uint32_t ntp_frac,
|
||||
uint32_t rtp_timestamp,
|
||||
RtcpList* rtcp_list,
|
||||
bool* new_rtcp_sr);
|
||||
|
||||
// Converts an RTP timestamp to the NTP domain in milliseconds using two
|
||||
// (RTP timestamp, NTP timestamp) pairs.
|
||||
bool RtpToNtpMs(int64_t rtp_timestamp, const RtcpList& rtcp,
|
||||
int64_t* timestamp_in_ms);
|
||||
|
||||
// Returns 1 there has been a forward wrap around, 0 if there has been no wrap
|
||||
// around and -1 if there has been a backwards wrap around (i.e. reordering).
|
||||
int CheckForWrapArounds(uint32_t rtp_timestamp, uint32_t rtcp_rtp_timestamp);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INTERFACE_RTP_TO_NTP_H_
|
68
jni/webrtc/system_wrappers/interface/rw_lock_wrapper.h
Normal file
68
jni/webrtc/system_wrappers/interface/rw_lock_wrapper.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/thread_annotations.h"
|
||||
|
||||
// Note, Windows pre-Vista version of RW locks are not supported natively. For
|
||||
// these OSs regular critical sections have been used to approximate RW lock
|
||||
// functionality and will therefore have worse performance.
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class LOCKABLE RWLockWrapper {
|
||||
public:
|
||||
static RWLockWrapper* CreateRWLock();
|
||||
virtual ~RWLockWrapper() {}
|
||||
|
||||
virtual void AcquireLockExclusive() EXCLUSIVE_LOCK_FUNCTION() = 0;
|
||||
virtual void ReleaseLockExclusive() UNLOCK_FUNCTION() = 0;
|
||||
|
||||
virtual void AcquireLockShared() SHARED_LOCK_FUNCTION() = 0;
|
||||
virtual void ReleaseLockShared() UNLOCK_FUNCTION() = 0;
|
||||
};
|
||||
|
||||
// RAII extensions of the RW lock. Prevents Acquire/Release missmatches and
|
||||
// provides more compact locking syntax.
|
||||
class SCOPED_LOCKABLE ReadLockScoped {
|
||||
public:
|
||||
ReadLockScoped(RWLockWrapper& rw_lock) SHARED_LOCK_FUNCTION(rw_lock)
|
||||
: rw_lock_(rw_lock) {
|
||||
rw_lock_.AcquireLockShared();
|
||||
}
|
||||
|
||||
~ReadLockScoped() UNLOCK_FUNCTION() {
|
||||
rw_lock_.ReleaseLockShared();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLockWrapper& rw_lock_;
|
||||
};
|
||||
|
||||
class SCOPED_LOCKABLE WriteLockScoped {
|
||||
public:
|
||||
WriteLockScoped(RWLockWrapper& rw_lock) EXCLUSIVE_LOCK_FUNCTION(rw_lock)
|
||||
: rw_lock_(rw_lock) {
|
||||
rw_lock_.AcquireLockExclusive();
|
||||
}
|
||||
|
||||
~WriteLockScoped() UNLOCK_FUNCTION() {
|
||||
rw_lock_.ReleaseLockExclusive();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLockWrapper& rw_lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
566
jni/webrtc/system_wrappers/interface/scoped_ptr.h
Normal file
566
jni/webrtc/system_wrappers/interface/scoped_ptr.h
Normal file
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/memory/scoped_ptr.h.
|
||||
|
||||
// Scopers help you manage ownership of a pointer, helping you easily manage the
|
||||
// a pointer within a scope, and automatically destroying the pointer at the
|
||||
// end of a scope. There are two main classes you will use, which correspond
|
||||
// to the operators new/delete and new[]/delete[].
|
||||
//
|
||||
// Example usage (scoped_ptr<T>):
|
||||
// {
|
||||
// scoped_ptr<Foo> foo(new Foo("wee"));
|
||||
// } // foo goes out of scope, releasing the pointer with it.
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> foo; // No pointer managed.
|
||||
// foo.reset(new Foo("wee")); // Now a pointer is managed.
|
||||
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
|
||||
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
|
||||
// foo->Method(); // Foo::Method() called.
|
||||
// foo.get()->Method(); // Foo::Method() called.
|
||||
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
|
||||
// // manages a pointer.
|
||||
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
|
||||
// foo.reset(); // Foo("wee4") destroyed, foo no longer
|
||||
// // manages a pointer.
|
||||
// } // foo wasn't managing a pointer, so nothing was destroyed.
|
||||
//
|
||||
// Example usage (scoped_ptr<T[]>):
|
||||
// {
|
||||
// scoped_ptr<Foo[]> foo(new Foo[100]);
|
||||
// foo.get()->Method(); // Foo::Method on the 0th element.
|
||||
// foo[10].Method(); // Foo::Method on the 10th element.
|
||||
// }
|
||||
//
|
||||
// These scopers also implement part of the functionality of C++11 unique_ptr
|
||||
// in that they are "movable but not copyable." You can use the scopers in
|
||||
// the parameter and return types of functions to signify ownership transfer
|
||||
// in to and out of a function. When calling a function that has a scoper
|
||||
// as the argument type, it must be called with the result of an analogous
|
||||
// scoper's Pass() function or another function that generates a temporary;
|
||||
// passing by copy will NOT work. Here is an example using scoped_ptr:
|
||||
//
|
||||
// void TakesOwnership(scoped_ptr<Foo> arg) {
|
||||
// // Do something with arg
|
||||
// }
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// // No need for calling Pass() because we are constructing a temporary
|
||||
// // for the return value.
|
||||
// return scoped_ptr<Foo>(new Foo("new"));
|
||||
// }
|
||||
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
|
||||
// return arg.Pass();
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
|
||||
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
|
||||
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
|
||||
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
|
||||
// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
|
||||
// }
|
||||
//
|
||||
// Notice that if you do not call Pass() when returning from PassThru(), or
|
||||
// when invoking TakesOwnership(), the code will not compile because scopers
|
||||
// are not copyable; they only implement move semantics which require calling
|
||||
// the Pass() function to signify a destructive transfer of state. CreateFoo()
|
||||
// is different though because we are constructing a temporary on the return
|
||||
// line and thus can avoid needing to call Pass().
|
||||
//
|
||||
// Pass() properly handles upcast in initialization, i.e. you can use a
|
||||
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
|
||||
//
|
||||
// scoped_ptr<Foo> foo(new Foo());
|
||||
// scoped_ptr<FooParent> parent(foo.Pass());
|
||||
//
|
||||
// PassAs<>() should be used to upcast return value in return statement:
|
||||
//
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// scoped_ptr<FooChild> result(new FooChild());
|
||||
// return result.PassAs<Foo>();
|
||||
// }
|
||||
//
|
||||
// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
|
||||
// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
|
||||
|
||||
// This is an implementation designed to match the anticipated future TR2
|
||||
// implementation of the scoped_ptr class.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm> // For std::swap().
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/system_wrappers/interface/compile_assert.h"
|
||||
#include "webrtc/system_wrappers/interface/template_util.h"
|
||||
#include "webrtc/system_wrappers/source/move.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Function object which deletes its parameter, which must be a pointer.
|
||||
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
|
||||
// invokes 'delete'. The default deleter for scoped_ptr<T>.
|
||||
template <class T>
|
||||
struct DefaultDeleter {
|
||||
DefaultDeleter() {}
|
||||
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
|
||||
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
|
||||
// if U* is implicitly convertible to T* and U is not an array type.
|
||||
//
|
||||
// Correct implementation should use SFINAE to disable this
|
||||
// constructor. However, since there are no other 1-argument constructors,
|
||||
// using a COMPILE_ASSERT() based on is_convertible<> and requiring
|
||||
// complete types is simpler and will cause compile failures for equivalent
|
||||
// misuses.
|
||||
//
|
||||
// Note, the is_convertible<U*, T*> check also ensures that U is not an
|
||||
// array. T is guaranteed to be a non-array, so any U* where U is an array
|
||||
// cannot convert to T*.
|
||||
enum { T_must_be_complete = sizeof(T) };
|
||||
enum { U_must_be_complete = sizeof(U) };
|
||||
COMPILE_ASSERT((webrtc::is_convertible<U*, T*>::value),
|
||||
U_ptr_must_implicitly_convert_to_T_ptr);
|
||||
}
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of DefaultDeleter for array types.
|
||||
template <class T>
|
||||
struct DefaultDeleter<T[]> {
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable this operator for any U != T because it is undefined to execute
|
||||
// an array delete when the static type of the array mismatches the dynamic
|
||||
// type.
|
||||
//
|
||||
// References:
|
||||
// C++98 [expr.delete]p3
|
||||
// http://cplusplus.github.com/LWG/lwg-defects.html#938
|
||||
template <typename U> void operator()(U* array) const;
|
||||
};
|
||||
|
||||
template <class T, int n>
|
||||
struct DefaultDeleter<T[n]> {
|
||||
// Never allow someone to declare something like scoped_ptr<int[10]>.
|
||||
COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
|
||||
};
|
||||
|
||||
// Function object which invokes 'free' on its parameter, which must be
|
||||
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
|
||||
//
|
||||
// scoped_ptr<int, webrtc::FreeDeleter> foo_ptr(
|
||||
// static_cast<int*>(malloc(sizeof(int))));
|
||||
struct FreeDeleter {
|
||||
inline void operator()(void* ptr) const {
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Minimal implementation of the core logic of scoped_ptr, suitable for
|
||||
// reuse in both scoped_ptr and its specializations.
|
||||
template <class T, class D>
|
||||
class scoped_ptr_impl {
|
||||
public:
|
||||
explicit scoped_ptr_impl(T* p) : data_(p) { }
|
||||
|
||||
// Initializer for deleters that have data parameters.
|
||||
scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
|
||||
|
||||
// Templated constructor that destructively takes the value from another
|
||||
// scoped_ptr_impl.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
|
||||
: data_(other->release(), other->get_deleter()) {
|
||||
// We do not support move-only deleters. We could modify our move
|
||||
// emulation to have webrtc::subtle::move() and webrtc::subtle::forward()
|
||||
// functions that are imperfect emulations of their C++11 equivalents,
|
||||
// but until there's a requirement, just assume deleters are copyable.
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
void TakeState(scoped_ptr_impl<U, V>* other) {
|
||||
// See comment in templated constructor above regarding lack of support
|
||||
// for move-only deleters.
|
||||
reset(other->release());
|
||||
get_deleter() = other->get_deleter();
|
||||
}
|
||||
|
||||
~scoped_ptr_impl() {
|
||||
if (data_.ptr != NULL) {
|
||||
// Not using get_deleter() saves one function call in non-optimized
|
||||
// builds.
|
||||
static_cast<D&>(data_)(data_.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(T* p) {
|
||||
// This is a self-reset, which is no longer allowed: http://crbug.com/162971
|
||||
if (p != NULL && p == data_.ptr)
|
||||
abort();
|
||||
|
||||
// Note that running data_.ptr = p can lead to undefined behavior if
|
||||
// get_deleter()(get()) deletes this. In order to pevent this, reset()
|
||||
// should update the stored pointer before deleting its old value.
|
||||
//
|
||||
// However, changing reset() to use that behavior may cause current code to
|
||||
// break in unexpected ways. If the destruction of the owned object
|
||||
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
|
||||
// then it will incorrectly dispatch calls to |p| rather than the original
|
||||
// value of |data_.ptr|.
|
||||
//
|
||||
// During the transition period, set the stored pointer to NULL while
|
||||
// deleting the object. Eventually, this safety check will be removed to
|
||||
// prevent the scenario initially described from occuring and
|
||||
// http://crbug.com/176091 can be closed.
|
||||
T* old = data_.ptr;
|
||||
data_.ptr = NULL;
|
||||
if (old != NULL)
|
||||
static_cast<D&>(data_)(old);
|
||||
data_.ptr = p;
|
||||
}
|
||||
|
||||
T* get() const { return data_.ptr; }
|
||||
|
||||
D& get_deleter() { return data_; }
|
||||
const D& get_deleter() const { return data_; }
|
||||
|
||||
void swap(scoped_ptr_impl& p2) {
|
||||
// Standard swap idiom: 'using std::swap' ensures that std::swap is
|
||||
// present in the overload set, but we call swap unqualified so that
|
||||
// any more-specific overloads can be used, if available.
|
||||
using std::swap;
|
||||
swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
|
||||
swap(data_.ptr, p2.data_.ptr);
|
||||
}
|
||||
|
||||
T* release() {
|
||||
T* old_ptr = data_.ptr;
|
||||
data_.ptr = NULL;
|
||||
return old_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to allow type-converting constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr_impl;
|
||||
|
||||
// Use the empty base class optimization to allow us to have a D
|
||||
// member, while avoiding any space overhead for it when D is an
|
||||
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
|
||||
// discussion of this technique.
|
||||
struct Data : public D {
|
||||
explicit Data(T* ptr_in) : ptr(ptr_in) {}
|
||||
Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
Data data_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||
// automatically deletes the pointer it holds (if any).
|
||||
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
|
||||
// Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||
// dereference it, you get the thread safety guarantees of T.
|
||||
//
|
||||
// The size of scoped_ptr is small. On most compilers, when using the
|
||||
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
|
||||
// increase the size proportional to whatever state they need to have. See
|
||||
// comments inside scoped_ptr_impl<> for details.
|
||||
//
|
||||
// Current implementation targets having a strict subset of C++11's
|
||||
// unique_ptr<> features. Known deficiencies include not supporting move-only
|
||||
// deleteres, function pointers as deleters, and deleters with reference
|
||||
// types.
|
||||
template <class T, class D = webrtc::DefaultDeleter<T> >
|
||||
class scoped_ptr {
|
||||
WEBRTC_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. Takes ownership of p.
|
||||
explicit scoped_ptr(element_type* p) : impl_(p) { }
|
||||
|
||||
// Constructor. Allows initialization of a stateful deleter.
|
||||
scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
|
||||
|
||||
// Constructor. Allows construction from a scoped_ptr rvalue for a
|
||||
// convertible type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
|
||||
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
|
||||
// has different post-conditions if D is a reference type. Since this
|
||||
// implementation does not support deleters with reference type,
|
||||
// we do not need a separate move constructor allowing us to avoid one
|
||||
// use of SFINAE. You only need to care about this if you modify the
|
||||
// implementation of scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
|
||||
COMPILE_ASSERT(!webrtc::is_array<U>::value, U_cannot_be_an_array);
|
||||
}
|
||||
|
||||
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||
|
||||
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
|
||||
// type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
|
||||
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
|
||||
// form has different requirements on for move-only Deleters. Since this
|
||||
// implementation does not support move-only Deleters, we do not need a
|
||||
// separate move assignment operator allowing us to avoid one use of SFINAE.
|
||||
// You only need to care about this if you modify the implementation of
|
||||
// scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
|
||||
COMPILE_ASSERT(!webrtc::is_array<U>::value, U_cannot_be_an_array);
|
||||
impl_.TakeState(&rhs.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset. Deletes the currently owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* p = NULL) { impl_.reset(p); }
|
||||
|
||||
// Accessors to get the owned object.
|
||||
// operator* and operator-> will assert() if there is no current object.
|
||||
element_type& operator*() const {
|
||||
assert(impl_.get() != NULL);
|
||||
return *impl_.get();
|
||||
}
|
||||
element_type* operator->() const {
|
||||
assert(impl_.get() != NULL);
|
||||
return impl_.get();
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
//
|
||||
// Note that this trick is only safe when the == and != operators
|
||||
// are declared explicitly, as otherwise "scoped_ptr1 ==
|
||||
// scoped_ptr2" will compile but do the wrong thing (i.e., convert
|
||||
// to Testable and then do the comparison).
|
||||
private:
|
||||
typedef webrtc::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(const element_type* p) const { return impl_.get() == p; }
|
||||
bool operator!=(const element_type* p) const { return impl_.get() != p; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
// C++98 doesn't support functions templates with default parameters which
|
||||
// makes it hard to write a PassAs() that understands converting the deleter
|
||||
// while preserving simple calling semantics.
|
||||
//
|
||||
// Until there is a use case for PassAs() with custom deleters, just ignore
|
||||
// the custom deleter.
|
||||
template <typename PassAsType>
|
||||
scoped_ptr<PassAsType> PassAs() {
|
||||
return scoped_ptr<PassAsType>(Pass());
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to reach into |impl_| in the constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr;
|
||||
webrtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Forbidden for API compatibility with std::unique_ptr.
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
class scoped_ptr<T[], D> {
|
||||
WEBRTC_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||
|
||||
public:
|
||||
// The element and deleter types.
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// Constructor. Defaults to initializing with NULL.
|
||||
scoped_ptr() : impl_(NULL) { }
|
||||
|
||||
// Constructor. Stores the given array. Note that the argument's type
|
||||
// must exactly match T*. In particular:
|
||||
// - it cannot be a pointer to a type derived from T, because it is
|
||||
// inherently unsafe in the general case to access an array through a
|
||||
// pointer whose dynamic type does not match its static type (eg., if
|
||||
// T and the derived types had different sizes access would be
|
||||
// incorrectly calculated). Deletion is also always undefined
|
||||
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
|
||||
// - it cannot be NULL, because NULL is an integral expression, not a
|
||||
// pointer to T. Use the no-argument version instead of explicitly
|
||||
// passing NULL.
|
||||
// - it cannot be const-qualified differently from T per unique_ptr spec
|
||||
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
|
||||
// to work around this may use implicit_cast<const T*>().
|
||||
// However, because of the first bullet in this comment, users MUST
|
||||
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
|
||||
explicit scoped_ptr(element_type* array) : impl_(array) { }
|
||||
|
||||
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||
|
||||
// operator=. Move operator= for C++03 move emulation of this type.
|
||||
scoped_ptr& operator=(RValue rhs) {
|
||||
impl_.TakeState(&rhs.object->impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset. Deletes the currently owned array, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* array = NULL) { impl_.reset(array); }
|
||||
|
||||
// Accessors to get the owned array.
|
||||
element_type& operator[](size_t i) const {
|
||||
assert(impl_.get() != NULL);
|
||||
return impl_.get()[i];
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
private:
|
||||
typedef webrtc::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(element_type* array) const { return impl_.get() == array; }
|
||||
bool operator!=(element_type* array) const { return impl_.get() != array; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
private:
|
||||
// Force element_type to be a complete type.
|
||||
enum { type_must_be_complete = sizeof(element_type) };
|
||||
|
||||
// Actually hold the data.
|
||||
webrtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Disable initialization from any type other than element_type*, by
|
||||
// providing a constructor that matches such an initialization, but is
|
||||
// private and has no definition. This is disabled because it is not safe to
|
||||
// call delete[] on an array whose static type does not match its dynamic
|
||||
// type.
|
||||
template <typename U> explicit scoped_ptr(U* array);
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Disable reset() from any type other than element_type*, for the same
|
||||
// reasons as the constructor above.
|
||||
template <typename U> void reset(U* array);
|
||||
void reset(int disallow_reset_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
// Free functions
|
||||
template <class T, class D>
|
||||
void swap(webrtc::scoped_ptr<T, D>& p1, webrtc::scoped_ptr<T, D>& p2) {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator==(T* p1, const webrtc::scoped_ptr<T, D>& p2) {
|
||||
return p1 == p2.get();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator!=(T* p1, const webrtc::scoped_ptr<T, D>& p2) {
|
||||
return p1 != p2.get();
|
||||
}
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
|
144
jni/webrtc/system_wrappers/interface/scoped_refptr.h
Normal file
144
jni/webrtc/system_wrappers/interface/scoped_refptr.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
|
||||
#define SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Extracted from Chromium's src/base/memory/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
|
||||
// avoid common memory leaks caused by forgetting to Release an object
|
||||
// reference. Sample usage:
|
||||
//
|
||||
// class MyFoo : public RefCounted<MyFoo> {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// void some_function() {
|
||||
// scoped_refptr<MyFoo> foo = new MyFoo();
|
||||
// foo->Method(param);
|
||||
// // |foo| is released when this function returns
|
||||
// }
|
||||
//
|
||||
// void some_other_function() {
|
||||
// scoped_refptr<MyFoo> foo = new MyFoo();
|
||||
// ...
|
||||
// foo = NULL; // explicitly releases |foo|
|
||||
// ...
|
||||
// if (foo)
|
||||
// foo->Method(param);
|
||||
// }
|
||||
//
|
||||
// The above examples show how scoped_refptr<T> acts like a pointer to T.
|
||||
// Given two scoped_refptr<T> classes, it is also possible to exchange
|
||||
// references between the two objects, like so:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = new MyFoo();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b.swap(a);
|
||||
// // now, |b| references the MyFoo object, and |a| references NULL.
|
||||
// }
|
||||
//
|
||||
// To make both |a| and |b| in the above example reference the same MyFoo
|
||||
// object, simply use the assignment operator:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = new MyFoo();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b = a;
|
||||
// // now, |a| and |b| each own a reference to the same MyFoo object.
|
||||
// }
|
||||
//
|
||||
template <class T>
|
||||
class scoped_refptr {
|
||||
public:
|
||||
scoped_refptr() : ptr_(NULL) {
|
||||
}
|
||||
|
||||
scoped_refptr(T* p) : ptr_(p) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
~scoped_refptr() {
|
||||
if (ptr_)
|
||||
ptr_->Release();
|
||||
}
|
||||
|
||||
T* get() const { return ptr_; }
|
||||
operator T*() const { return ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
|
||||
// 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.
|
||||
T* release() {
|
||||
T* retVal = ptr_;
|
||||
ptr_ = NULL;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(T* p) {
|
||||
// AddRef first so that self assignment should work
|
||||
if (p)
|
||||
p->AddRef();
|
||||
if (ptr_ )
|
||||
ptr_->Release();
|
||||
ptr_ = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
|
||||
return *this = r.ptr_;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
|
||||
return *this = r.get();
|
||||
}
|
||||
|
||||
void swap(T** pp) {
|
||||
T* p = ptr_;
|
||||
ptr_ = *pp;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void swap(scoped_refptr<T>& r) {
|
||||
swap(&r.ptr_);
|
||||
}
|
||||
|
||||
protected:
|
||||
T* ptr_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
|
149
jni/webrtc/system_wrappers/interface/scoped_vector.h
Normal file
149
jni/webrtc/system_wrappers/interface/scoped_vector.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/memory/scoped_vector.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_VECTOR_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_VECTOR_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/stl_util.h"
|
||||
#include "webrtc/system_wrappers/source/move.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// ScopedVector wraps a vector deleting the elements from its
|
||||
// destructor.
|
||||
template <class T>
|
||||
class ScopedVector {
|
||||
WEBRTC_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedVector, RValue)
|
||||
|
||||
public:
|
||||
typedef typename std::vector<T*>::allocator_type allocator_type;
|
||||
typedef typename std::vector<T*>::size_type size_type;
|
||||
typedef typename std::vector<T*>::difference_type difference_type;
|
||||
typedef typename std::vector<T*>::pointer pointer;
|
||||
typedef typename std::vector<T*>::const_pointer const_pointer;
|
||||
typedef typename std::vector<T*>::reference reference;
|
||||
typedef typename std::vector<T*>::const_reference const_reference;
|
||||
typedef typename std::vector<T*>::value_type value_type;
|
||||
typedef typename std::vector<T*>::iterator iterator;
|
||||
typedef typename std::vector<T*>::const_iterator const_iterator;
|
||||
typedef typename std::vector<T*>::reverse_iterator reverse_iterator;
|
||||
typedef typename std::vector<T*>::const_reverse_iterator
|
||||
const_reverse_iterator;
|
||||
|
||||
ScopedVector() {}
|
||||
~ScopedVector() { clear(); }
|
||||
ScopedVector(RValue other) { swap(*other.object); }
|
||||
|
||||
ScopedVector& operator=(RValue rhs) {
|
||||
swap(*rhs.object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator[](size_t index) { return v_[index]; }
|
||||
const_reference operator[](size_t index) const { return v_[index]; }
|
||||
|
||||
bool empty() const { return v_.empty(); }
|
||||
size_t size() const { return v_.size(); }
|
||||
|
||||
reverse_iterator rbegin() { return v_.rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return v_.rbegin(); }
|
||||
reverse_iterator rend() { return v_.rend(); }
|
||||
const_reverse_iterator rend() const { return v_.rend(); }
|
||||
|
||||
iterator begin() { return v_.begin(); }
|
||||
const_iterator begin() const { return v_.begin(); }
|
||||
iterator end() { return v_.end(); }
|
||||
const_iterator end() const { return v_.end(); }
|
||||
|
||||
const_reference front() const { return v_.front(); }
|
||||
reference front() { return v_.front(); }
|
||||
const_reference back() const { return v_.back(); }
|
||||
reference back() { return v_.back(); }
|
||||
|
||||
void push_back(T* elem) { v_.push_back(elem); }
|
||||
|
||||
void pop_back() {
|
||||
assert(!empty());
|
||||
delete v_.back();
|
||||
v_.pop_back();
|
||||
}
|
||||
|
||||
std::vector<T*>& get() { return v_; }
|
||||
const std::vector<T*>& get() const { return v_; }
|
||||
void swap(std::vector<T*>& other) { v_.swap(other); }
|
||||
void swap(ScopedVector<T>& other) { v_.swap(other.v_); }
|
||||
void release(std::vector<T*>* out) {
|
||||
out->swap(v_);
|
||||
v_.clear();
|
||||
}
|
||||
|
||||
void reserve(size_t capacity) { v_.reserve(capacity); }
|
||||
|
||||
// Resize, deleting elements in the disappearing range if we are shrinking.
|
||||
void resize(size_t new_size) {
|
||||
if (v_.size() > new_size)
|
||||
STLDeleteContainerPointers(v_.begin() + new_size, v_.end());
|
||||
v_.resize(new_size);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
void assign(InputIterator begin, InputIterator end) {
|
||||
v_.assign(begin, end);
|
||||
}
|
||||
|
||||
void clear() { STLDeleteElements(&v_); }
|
||||
|
||||
// Like |clear()|, but doesn't delete any elements.
|
||||
void weak_clear() { v_.clear(); }
|
||||
|
||||
// Lets the ScopedVector take ownership of |x|.
|
||||
iterator insert(iterator position, T* x) {
|
||||
return v_.insert(position, x);
|
||||
}
|
||||
|
||||
// Lets the ScopedVector take ownership of elements in [first,last).
|
||||
template<typename InputIterator>
|
||||
void insert(iterator position, InputIterator first, InputIterator last) {
|
||||
v_.insert(position, first, last);
|
||||
}
|
||||
|
||||
iterator erase(iterator position) {
|
||||
delete *position;
|
||||
return v_.erase(position);
|
||||
}
|
||||
|
||||
iterator erase(iterator first, iterator last) {
|
||||
STLDeleteContainerPointers(first, last);
|
||||
return v_.erase(first, last);
|
||||
}
|
||||
|
||||
// Like |erase()|, but doesn't delete the element at |position|.
|
||||
iterator weak_erase(iterator position) {
|
||||
return v_.erase(position);
|
||||
}
|
||||
|
||||
// Like |erase()|, but doesn't delete the elements in [first, last).
|
||||
iterator weak_erase(iterator first, iterator last) {
|
||||
return v_.erase(first, last);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T*> v_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_VECTOR_H_
|
24
jni/webrtc/system_wrappers/interface/sleep.h
Normal file
24
jni/webrtc/system_wrappers/interface/sleep.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This function sleeps for the specified number of milliseconds.
|
||||
// It may return early if the thread is woken by some other event,
|
||||
// such as the delivery of a signal on Unix.
|
||||
void SleepMs(int msecs);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
65
jni/webrtc/system_wrappers/interface/sort.h
Normal file
65
jni/webrtc/system_wrappers/interface/sort.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Generic unstable sorting routines.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum Type {
|
||||
TYPE_Word8,
|
||||
TYPE_UWord8,
|
||||
TYPE_Word16,
|
||||
TYPE_UWord16,
|
||||
TYPE_Word32,
|
||||
TYPE_UWord32,
|
||||
TYPE_Word64,
|
||||
TYPE_UWord64,
|
||||
TYPE_Float32,
|
||||
TYPE_Float64
|
||||
};
|
||||
|
||||
// Sorts intrinsic data types.
|
||||
//
|
||||
// data [in/out] A pointer to an array of intrinsic type.
|
||||
// Upon return it will be sorted in ascending order.
|
||||
// num_of_elements The number of elements in the array.
|
||||
// data_type Enum corresponding to the type of the array.
|
||||
//
|
||||
// returns 0 on success, -1 on failure.
|
||||
int32_t Sort(void* data, uint32_t num_of_elements, Type data_type);
|
||||
|
||||
// Sorts arbitrary data types. This requires an array of intrinsically typed
|
||||
// key values which will be used to sort the data array. There must be a
|
||||
// one-to-one correspondence between data elements and key elements, with
|
||||
// corresponding elements sharing the same position in their respective
|
||||
// arrays.
|
||||
//
|
||||
// data [in/out] A pointer to an array of arbitrary type.
|
||||
// Upon return it will be sorted in ascending order.
|
||||
// key [in] A pointer to an array of keys used to sort the
|
||||
// data array.
|
||||
// num_of_elements The number of elements in the arrays.
|
||||
// size_of_element The size, in bytes, of the data array.
|
||||
// key_type Enum corresponding to the type of the key array.
|
||||
//
|
||||
// returns 0 on success, -1 on failure.
|
||||
//
|
||||
int32_t KeySort(void* data, void* key, uint32_t num_of_elements,
|
||||
uint32_t size_of_element, Type key_type);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
153
jni/webrtc/system_wrappers/interface/static_instance.h
Normal file
153
jni/webrtc/system_wrappers/interface/static_instance.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum CountOperation {
|
||||
kRelease,
|
||||
kAddRef,
|
||||
kAddRefNoCreate
|
||||
};
|
||||
enum CreateOperation {
|
||||
kInstanceExists,
|
||||
kCreate,
|
||||
kDestroy
|
||||
};
|
||||
|
||||
template <class T>
|
||||
// Construct On First Use idiom. Avoids
|
||||
// "static initialization order fiasco".
|
||||
static T* GetStaticInstance(CountOperation count_operation) {
|
||||
// TODO (hellner): use atomic wrapper instead.
|
||||
static volatile long instance_count = 0;
|
||||
static T* volatile instance = NULL;
|
||||
CreateOperation state = kInstanceExists;
|
||||
#ifndef _WIN32
|
||||
// This memory is staticly allocated once. The application does not try to
|
||||
// free this memory. This approach is taken to avoid issues with
|
||||
// destruction order for statically allocated memory. The memory will be
|
||||
// reclaimed by the OS and memory leak tools will not recognize memory
|
||||
// reachable from statics leaked so no noise is added by doing this.
|
||||
static CriticalSectionWrapper* crit_sect(
|
||||
CriticalSectionWrapper::CreateCriticalSection());
|
||||
CriticalSectionScoped lock(crit_sect);
|
||||
|
||||
if (count_operation ==
|
||||
kAddRefNoCreate && instance_count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (count_operation ==
|
||||
kAddRef ||
|
||||
count_operation == kAddRefNoCreate) {
|
||||
instance_count++;
|
||||
if (instance_count == 1) {
|
||||
state = kCreate;
|
||||
}
|
||||
} else {
|
||||
instance_count--;
|
||||
if (instance_count == 0) {
|
||||
state = kDestroy;
|
||||
}
|
||||
}
|
||||
if (state == kCreate) {
|
||||
instance = T::CreateInstance();
|
||||
} else if (state == kDestroy) {
|
||||
T* old_instance = instance;
|
||||
instance = NULL;
|
||||
// The state will not change past this point. Release the critical
|
||||
// section while deleting the object in case it would be blocking on
|
||||
// access back to this object. (This is the case for the tracing class
|
||||
// since the thread owned by the tracing class also traces).
|
||||
// TODO(hellner): this is a bit out of place but here goes, de-couple
|
||||
// thread implementation with trace implementation.
|
||||
crit_sect->Leave();
|
||||
if (old_instance) {
|
||||
delete old_instance;
|
||||
}
|
||||
// Re-acquire the lock since the scoped critical section will release
|
||||
// it.
|
||||
crit_sect->Enter();
|
||||
return NULL;
|
||||
}
|
||||
#else // _WIN32
|
||||
if (count_operation ==
|
||||
kAddRefNoCreate && instance_count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (count_operation == kAddRefNoCreate) {
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
// The instance has been destroyed by some other thread. Rollback.
|
||||
InterlockedDecrement(&instance_count);
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
// Sanity to catch corrupt state.
|
||||
if (instance == NULL) {
|
||||
assert(false);
|
||||
InterlockedDecrement(&instance_count);
|
||||
return NULL;
|
||||
}
|
||||
} else if (count_operation == kAddRef) {
|
||||
if (instance_count == 0) {
|
||||
state = kCreate;
|
||||
} else {
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
// InterlockedDecrement because reference count should not be
|
||||
// updated just yet (that's done when the instance is created).
|
||||
InterlockedDecrement(&instance_count);
|
||||
state = kCreate;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int new_value = InterlockedDecrement(&instance_count);
|
||||
if (new_value == 0) {
|
||||
state = kDestroy;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == kCreate) {
|
||||
// Create instance and let whichever thread finishes first assign its
|
||||
// local copy to the global instance. All other threads reclaim their
|
||||
// local copy.
|
||||
T* new_instance = T::CreateInstance();
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&instance),
|
||||
new_instance);
|
||||
} else {
|
||||
InterlockedDecrement(&instance_count);
|
||||
if (new_instance) {
|
||||
delete static_cast<T*>(new_instance);
|
||||
}
|
||||
}
|
||||
} else if (state == kDestroy) {
|
||||
T* old_value = static_cast<T*>(InterlockedExchangePointer(
|
||||
reinterpret_cast<void * volatile*>(&instance), NULL));
|
||||
if (old_value) {
|
||||
delete static_cast<T*>(old_value);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif // #ifndef _WIN32
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namspace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
265
jni/webrtc/system_wrappers/interface/stl_util.h
Normal file
265
jni/webrtc/system_wrappers/interface/stl_util.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/stl_util.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Clears internal memory of an STL object.
|
||||
// STL clear()/reserve(0) does not always free internal memory allocated
|
||||
// This function uses swap/destructor to ensure the internal memory is freed.
|
||||
template<class T>
|
||||
void STLClearObject(T* obj) {
|
||||
T tmp;
|
||||
tmp.swap(*obj);
|
||||
// Sometimes "T tmp" allocates objects with memory (arena implementation?).
|
||||
// Hence using additional reserve(0) even if it doesn't always work.
|
||||
obj->reserve(0);
|
||||
}
|
||||
|
||||
// For a range within a container of pointers, calls delete (non-array version)
|
||||
// on these pointers.
|
||||
// NOTE: for these three functions, we could just implement a DeleteObject
|
||||
// functor and then call for_each() on the range and functor, but this
|
||||
// requires us to pull in all of algorithm.h, which seems expensive.
|
||||
// For hash_[multi]set, it is important that this deletes behind the iterator
|
||||
// because the hash_set may call the hash function on the iterator when it is
|
||||
// advanced, which could result in the hash function trying to deference a
|
||||
// stale pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete *temp;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete (non-array version) on
|
||||
// BOTH items in the pairs.
|
||||
// NOTE: Like STLDeleteContainerPointers, it is important that this deletes
|
||||
// behind the iterator because if both the key and value are deleted, the
|
||||
// container may call the hash function on the iterator when it is advanced,
|
||||
// which could result in the hash function trying to dereference a stale
|
||||
// pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->first;
|
||||
delete temp->second;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete (non-array version) on
|
||||
// the FIRST item in the pairs.
|
||||
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairFirstPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->first;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete.
|
||||
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
|
||||
// Deleting the value does not always invalidate the iterator, but it may
|
||||
// do so if the key is a pointer into the value object.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->second;
|
||||
}
|
||||
}
|
||||
|
||||
// To treat a possibly-empty vector as an array, use these functions.
|
||||
// If you know the array will never be empty, you can use &*v.begin()
|
||||
// directly, but that is undefined behaviour if |v| is empty.
|
||||
template<typename T>
|
||||
inline T* vector_as_array(std::vector<T>* v) {
|
||||
return v->empty() ? NULL : &*v->begin();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T* vector_as_array(const std::vector<T>* v) {
|
||||
return v->empty() ? NULL : &*v->begin();
|
||||
}
|
||||
|
||||
// Return a mutable char* pointing to a string's internal buffer,
|
||||
// which may not be null-terminated. Writing through this pointer will
|
||||
// modify the string.
|
||||
//
|
||||
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
|
||||
// next call to a string method that invalidates iterators.
|
||||
//
|
||||
// As of 2006-04, there is no standard-blessed way of getting a
|
||||
// mutable reference to a string's internal buffer. However, issue 530
|
||||
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
|
||||
// proposes this as the method. According to Matt Austern, this should
|
||||
// already work on all current implementations.
|
||||
inline char* string_as_array(std::string* str) {
|
||||
// DO NOT USE const_cast<char*>(str->data())
|
||||
return str->empty() ? NULL : &*str->begin();
|
||||
}
|
||||
|
||||
// The following functions are useful for cleaning up STL containers whose
|
||||
// elements point to allocated memory.
|
||||
|
||||
// STLDeleteElements() deletes all the elements in an STL container and clears
|
||||
// the container. This function is suitable for use with a vector, set,
|
||||
// hash_set, or any other STL container which defines sensible begin(), end(),
|
||||
// and clear() methods.
|
||||
//
|
||||
// If container is NULL, this function is a no-op.
|
||||
//
|
||||
// As an alternative to calling STLDeleteElements() directly, consider
|
||||
// STLElementDeleter (defined below), which ensures that your container's
|
||||
// elements are deleted when the STLElementDeleter goes out of scope.
|
||||
template <class T>
|
||||
void STLDeleteElements(T* container) {
|
||||
if (!container)
|
||||
return;
|
||||
STLDeleteContainerPointers(container->begin(), container->end());
|
||||
container->clear();
|
||||
}
|
||||
|
||||
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
|
||||
// deletes all the "value" components and clears the container. Does nothing
|
||||
// in the case it's given a NULL pointer.
|
||||
template <class T>
|
||||
void STLDeleteValues(T* container) {
|
||||
if (!container)
|
||||
return;
|
||||
for (typename T::iterator i(container->begin()); i != container->end(); ++i)
|
||||
delete i->second;
|
||||
container->clear();
|
||||
}
|
||||
|
||||
|
||||
// The following classes provide a convenient way to delete all elements or
|
||||
// values from STL containers when they goes out of scope. This greatly
|
||||
// simplifies code that creates temporary objects and has multiple return
|
||||
// statements. Example:
|
||||
//
|
||||
// vector<MyProto *> tmp_proto;
|
||||
// STLElementDeleter<vector<MyProto *> > d(&tmp_proto);
|
||||
// if (...) return false;
|
||||
// ...
|
||||
// return success;
|
||||
|
||||
// Given a pointer to an STL container this class will delete all the element
|
||||
// pointers when it goes out of scope.
|
||||
template<class T>
|
||||
class STLElementDeleter {
|
||||
public:
|
||||
STLElementDeleter<T>(T* container) : container_(container) {}
|
||||
~STLElementDeleter<T>() { STLDeleteElements(container_); }
|
||||
|
||||
private:
|
||||
T* container_;
|
||||
};
|
||||
|
||||
// Given a pointer to an STL container this class will delete all the value
|
||||
// pointers when it goes out of scope.
|
||||
template<class T>
|
||||
class STLValueDeleter {
|
||||
public:
|
||||
STLValueDeleter<T>(T* container) : container_(container) {}
|
||||
~STLValueDeleter<T>() { STLDeleteValues(container_); }
|
||||
|
||||
private:
|
||||
T* container_;
|
||||
};
|
||||
|
||||
// Test to see if a set, map, hash_set or hash_map contains a particular key.
|
||||
// Returns true if the key is in the collection.
|
||||
template <typename Collection, typename Key>
|
||||
bool ContainsKey(const Collection& collection, const Key& key) {
|
||||
return collection.find(key) != collection.end();
|
||||
}
|
||||
|
||||
// Returns true if the container is sorted.
|
||||
template <typename Container>
|
||||
bool STLIsSorted(const Container& cont) {
|
||||
// Note: Use reverse iterator on container to ensure we only require
|
||||
// value_type to implement operator<.
|
||||
return std::adjacent_find(cont.rbegin(), cont.rend(),
|
||||
std::less<typename Container::value_type>())
|
||||
== cont.rend();
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the difference of two sorted containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType difference;
|
||||
std::set_difference(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(difference, difference.end()));
|
||||
return difference;
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the union of two sorted containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType result;
|
||||
std::set_union(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(result, result.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the intersection of two sorted
|
||||
// containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType result;
|
||||
std::set_intersection(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(result, result.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns true if the sorted container |a1| contains all elements of the sorted
|
||||
// container |a2|.
|
||||
template <typename Arg1, typename Arg2>
|
||||
bool STLIncludes(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
return std::includes(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
38
jni/webrtc/system_wrappers/interface/stringize_macros.h
Normal file
38
jni/webrtc/system_wrappers/interface/stringize_macros.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Modified from the Chromium original:
|
||||
// src/base/strings/stringize_macros.h
|
||||
|
||||
// This file defines preprocessor macros for stringizing preprocessor
|
||||
// symbols (or their output) and manipulating preprocessor symbols
|
||||
// that define strings.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STRINGIZE_MACROS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STRINGIZE_MACROS_H_
|
||||
|
||||
// This is not very useful as it does not expand defined symbols if
|
||||
// called directly. Use its counterpart without the _NO_EXPANSION
|
||||
// suffix, below.
|
||||
#define STRINGIZE_NO_EXPANSION(x) #x
|
||||
|
||||
// Use this to quote the provided parameter, first expanding it if it
|
||||
// is a preprocessor symbol.
|
||||
//
|
||||
// For example, if:
|
||||
// #define A FOO
|
||||
// #define B(x) myobj->FunctionCall(x)
|
||||
//
|
||||
// Then:
|
||||
// STRINGIZE(A) produces "FOO"
|
||||
// STRINGIZE(B(y)) produces "myobj->FunctionCall(y)"
|
||||
#define STRINGIZE(x) STRINGIZE_NO_EXPANSION(x)
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STRINGIZE_MACROS_H_
|
114
jni/webrtc/system_wrappers/interface/template_util.h
Normal file
114
jni/webrtc/system_wrappers/interface/template_util.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/template_util.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_
|
||||
|
||||
#include <stddef.h> // For size_t.
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Template definitions from tr1.
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
template <class T> struct is_pointer : false_type {};
|
||||
template <class T> struct is_pointer<T*> : true_type {};
|
||||
|
||||
template <class T, class U> struct is_same : public false_type {};
|
||||
template <class T> struct is_same<T, T> : true_type {};
|
||||
|
||||
template<class> struct is_array : public false_type {};
|
||||
template<class T, size_t n> struct is_array<T[n]> : public true_type {};
|
||||
template<class T> struct is_array<T[]> : public true_type {};
|
||||
|
||||
template <class T> struct is_non_const_reference : false_type {};
|
||||
template <class T> struct is_non_const_reference<T&> : true_type {};
|
||||
template <class T> struct is_non_const_reference<const T&> : false_type {};
|
||||
|
||||
template <class T> struct is_void : false_type {};
|
||||
template <> struct is_void<void> : true_type {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
|
||||
// sizeof(NoType).
|
||||
typedef char YesType;
|
||||
|
||||
struct NoType {
|
||||
YesType dummy[2];
|
||||
};
|
||||
|
||||
// This class is an implementation detail for is_convertible, and you
|
||||
// don't need to know how it works to use is_convertible. For those
|
||||
// who care: we declare two different functions, one whose argument is
|
||||
// of type To and one with a variadic argument list. We give them
|
||||
// return types of different size, so we can use sizeof to trick the
|
||||
// compiler into telling us which function it would have chosen if we
|
||||
// had called it with an argument of type From. See Alexandrescu's
|
||||
// _Modern C++ Design_ for more details on this sort of trick.
|
||||
|
||||
struct ConvertHelper {
|
||||
template <typename To>
|
||||
static YesType Test(To);
|
||||
|
||||
template <typename To>
|
||||
static NoType Test(...);
|
||||
|
||||
template <typename From>
|
||||
static From& Create();
|
||||
};
|
||||
|
||||
// Used to determine if a type is a struct/union/class. Inspired by Boost's
|
||||
// is_class type_trait implementation.
|
||||
struct IsClassHelper {
|
||||
template <typename C>
|
||||
static YesType Test(void(C::*)(void));
|
||||
|
||||
template <typename C>
|
||||
static NoType Test(...);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||
//
|
||||
// Note that if the type is convertible, this will be a true_type REGARDLESS
|
||||
// of whether or not the conversion would emit a warning.
|
||||
template <typename From, typename To>
|
||||
struct is_convertible
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::ConvertHelper::Test<To>(
|
||||
internal::ConvertHelper::Create<From>())) ==
|
||||
sizeof(internal::YesType)> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_class
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::IsClassHelper::Test<T>(0)) ==
|
||||
sizeof(internal::YesType)> {
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TEMPLATE_UTIL_H_
|
99
jni/webrtc/system_wrappers/interface/thread_annotations.h
Normal file
99
jni/webrtc/system_wrappers/interface/thread_annotations.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
// Borrowed from
|
||||
// https://code.google.com/p/gperftools/source/browse/src/base/thread_annotations.h
|
||||
// but adapted for clang attributes instead of the gcc.
|
||||
//
|
||||
// This header file contains the macro definitions for thread safety
|
||||
// annotations that allow the developers to document the locking policies
|
||||
// of their multi-threaded code. The annotations can also help program
|
||||
// analysis tools to identify potential thread safety issues.
|
||||
|
||||
#ifndef BASE_THREAD_ANNOTATIONS_H_
|
||||
#define BASE_THREAD_ANNOTATIONS_H_
|
||||
|
||||
#if defined(__clang__) && (!defined(SWIG))
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
#else
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||
#endif
|
||||
|
||||
// Document if a shared variable/field needs to be protected by a lock.
|
||||
// GUARDED_BY allows the user to specify a particular lock that should be
|
||||
// held when accessing the annotated variable, while GUARDED_VAR only
|
||||
// indicates a shared variable should be guarded (by any lock). GUARDED_VAR
|
||||
// is primarily used when the client cannot express the name of the lock.
|
||||
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||
#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded)
|
||||
|
||||
// Document if the memory location pointed to by a pointer should be guarded
|
||||
// by a lock when dereferencing the pointer. Similar to GUARDED_VAR,
|
||||
// PT_GUARDED_VAR is primarily used when the client cannot express the name
|
||||
// of the lock. Note that a pointer variable to a shared memory location
|
||||
// could itself be a shared variable. For example, if a shared global pointer
|
||||
// q, which is guarded by mu1, points to a shared memory location that is
|
||||
// guarded by mu2, q should be annotated as follows:
|
||||
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
|
||||
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x))
|
||||
#define PT_GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded)
|
||||
|
||||
// Document the acquisition order between locks that can be held
|
||||
// simultaneously by a thread. For any two locks that need to be annotated
|
||||
// to establish an acquisition order, only one of them needs the annotation.
|
||||
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
|
||||
// and ACQUIRED_BEFORE.)
|
||||
#define ACQUIRED_AFTER(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
|
||||
#define ACQUIRED_BEFORE(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
|
||||
|
||||
// The following three annotations document the lock requirements for
|
||||
// functions/methods.
|
||||
|
||||
// Document if a function expects certain locks to be held before it is called
|
||||
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
|
||||
|
||||
#define SHARED_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
|
||||
|
||||
// Document the locks acquired in the body of the function. These locks
|
||||
// cannot be held when calling this function (as google3's Mutex locks are
|
||||
// non-reentrant).
|
||||
#define LOCKS_EXCLUDED(x) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
|
||||
|
||||
// Document the lock the annotated function returns without acquiring it.
|
||||
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
// Document if a class/type is a lockable type (such as the Mutex class).
|
||||
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
|
||||
// Document if a class is a scoped lockable type (such as the MutexLock class).
|
||||
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
// The following annotations specify lock and unlock primitives.
|
||||
#define EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
|
||||
|
||||
#define SHARED_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
|
||||
|
||||
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
|
||||
|
||||
#define SHARED_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
|
||||
|
||||
#define UNLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
|
||||
|
||||
// An escape hatch for thread safety analysis to ignore the annotated function.
|
||||
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
#endif // BASE_THREAD_ANNOTATIONS_H_
|
92
jni/webrtc/system_wrappers/interface/thread_wrapper.h
Normal file
92
jni/webrtc/system_wrappers/interface/thread_wrapper.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// System independant wrapper for spawning threads
|
||||
// Note: the spawned thread will loop over the callback function until stopped.
|
||||
// Note: The callback function is expected to return every 2 seconds or more
|
||||
// often.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Object that will be passed by the spawned thread when it enters the callback
|
||||
// function.
|
||||
#define ThreadObj void*
|
||||
|
||||
// Callback function that the spawned thread will enter once spawned.
|
||||
// A return value of false is interpreted as that the function has no
|
||||
// more work to do and that the thread can be released.
|
||||
typedef bool(*ThreadRunFunction)(ThreadObj);
|
||||
|
||||
enum ThreadPriority {
|
||||
kLowPriority = 1,
|
||||
kNormalPriority = 2,
|
||||
kHighPriority = 3,
|
||||
kHighestPriority = 4,
|
||||
kRealtimePriority = 5
|
||||
};
|
||||
|
||||
class ThreadWrapper {
|
||||
public:
|
||||
enum {kThreadMaxNameLength = 64};
|
||||
|
||||
virtual ~ThreadWrapper() {};
|
||||
|
||||
// Factory method. Constructor disabled.
|
||||
//
|
||||
// func Pointer to a, by user, specified callback function.
|
||||
// obj Object associated with the thread. Passed in the callback
|
||||
// function.
|
||||
// prio Thread priority. May require root/admin rights.
|
||||
// thread_name NULL terminated thread name, will be visable in the Windows
|
||||
// debugger.
|
||||
static ThreadWrapper* CreateThread(ThreadRunFunction func,
|
||||
ThreadObj obj,
|
||||
ThreadPriority prio = kNormalPriority,
|
||||
const char* thread_name = 0);
|
||||
|
||||
// Get the current thread's kernel thread ID.
|
||||
static uint32_t GetThreadId();
|
||||
|
||||
// Non blocking termination of the spawned thread. Note that it is not safe
|
||||
// to delete this class until the spawned thread has been reclaimed.
|
||||
virtual void SetNotAlive() = 0;
|
||||
|
||||
// Tries to spawns a thread and returns true if that was successful.
|
||||
// Additionally, it tries to set thread priority according to the priority
|
||||
// from when CreateThread was called. However, failure to set priority will
|
||||
// not result in a false return value.
|
||||
// TODO(henrike): add a function for polling whether priority was set or
|
||||
// not.
|
||||
virtual bool Start(unsigned int& id) = 0;
|
||||
|
||||
// Sets the threads CPU affinity. CPUs are listed 0 - (number of CPUs - 1).
|
||||
// The numbers in processor_numbers specify which CPUs are allowed to run the
|
||||
// thread. processor_numbers should not contain any duplicates and elements
|
||||
// should be lower than (number of CPUs - 1). amount_of_processors should be
|
||||
// equal to the number of processors listed in processor_numbers.
|
||||
virtual bool SetAffinity(const int* processor_numbers,
|
||||
const unsigned int amount_of_processors);
|
||||
|
||||
// Stops the spawned thread and waits for it to be reclaimed with a timeout
|
||||
// of two seconds. Will return false if the thread was not reclaimed.
|
||||
// Multiple tries to Stop are allowed (e.g. to wait longer than 2 seconds).
|
||||
// It's ok to call Stop() even if the spawned thread has been reclaimed.
|
||||
virtual bool Stop() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
298
jni/webrtc/system_wrappers/interface/tick_util.h
Normal file
298
jni/webrtc/system_wrappers/interface/tick_util.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// System independant wrapper for polling elapsed time in ms and us.
|
||||
// The implementation works in the tick domain which can be mapped over to the
|
||||
// time domain.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
||||
|
||||
#if _WIN32
|
||||
// Note: The Windows header must always be included before mmsystem.h
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#elif WEBRTC_LINUX
|
||||
#include <time.h>
|
||||
#elif WEBRTC_MAC
|
||||
#include <mach/mach_time.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TickInterval;
|
||||
|
||||
// Class representing the current time.
|
||||
class TickTime {
|
||||
public:
|
||||
TickTime();
|
||||
explicit TickTime(int64_t ticks);
|
||||
|
||||
// Current time in the tick domain.
|
||||
static TickTime Now();
|
||||
|
||||
// Now in the time domain in ms.
|
||||
static int64_t MillisecondTimestamp();
|
||||
|
||||
// Now in the time domain in us.
|
||||
static int64_t MicrosecondTimestamp();
|
||||
|
||||
// Returns the number of ticks in the tick domain.
|
||||
int64_t Ticks() const;
|
||||
|
||||
static int64_t MillisecondsToTicks(const int64_t ms);
|
||||
|
||||
static int64_t TicksToMilliseconds(const int64_t ticks);
|
||||
|
||||
// Returns a TickTime that is ticks later than the passed TickTime.
|
||||
friend TickTime operator+(const TickTime lhs, const int64_t ticks);
|
||||
TickTime& operator+=(const int64_t& ticks);
|
||||
|
||||
// Returns a TickInterval that is the difference in ticks beween rhs and lhs.
|
||||
friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
|
||||
|
||||
// Call to engage the fake clock. This is useful for tests since relying on
|
||||
// a real clock often makes the test flaky.
|
||||
static void UseFakeClock(int64_t start_millisecond);
|
||||
|
||||
// Advance the fake clock. Must be called after UseFakeClock.
|
||||
static void AdvanceFakeClock(int64_t milliseconds);
|
||||
|
||||
private:
|
||||
static int64_t QueryOsForTicks();
|
||||
|
||||
static bool use_fake_clock_;
|
||||
static int64_t fake_ticks_;
|
||||
|
||||
int64_t ticks_;
|
||||
};
|
||||
|
||||
// Represents a time delta in ticks.
|
||||
class TickInterval {
|
||||
public:
|
||||
TickInterval();
|
||||
|
||||
int64_t Milliseconds() const;
|
||||
int64_t Microseconds() const;
|
||||
|
||||
// Returns the sum of two TickIntervals as a TickInterval.
|
||||
friend TickInterval operator+(const TickInterval& lhs,
|
||||
const TickInterval& rhs);
|
||||
TickInterval& operator+=(const TickInterval& rhs);
|
||||
|
||||
// Returns a TickInterval corresponding to rhs - lhs.
|
||||
friend TickInterval operator-(const TickInterval& lhs,
|
||||
const TickInterval& rhs);
|
||||
TickInterval& operator-=(const TickInterval& rhs);
|
||||
|
||||
friend bool operator>(const TickInterval& lhs, const TickInterval& rhs);
|
||||
friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs);
|
||||
friend bool operator<(const TickInterval& lhs, const TickInterval& rhs);
|
||||
friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs);
|
||||
|
||||
private:
|
||||
explicit TickInterval(int64_t interval);
|
||||
|
||||
friend class TickTime;
|
||||
friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
|
||||
|
||||
private:
|
||||
int64_t interval_;
|
||||
};
|
||||
|
||||
inline TickInterval operator+(const TickInterval& lhs,
|
||||
const TickInterval& rhs) {
|
||||
return TickInterval(lhs.interval_ + rhs.interval_);
|
||||
}
|
||||
|
||||
inline TickInterval operator-(const TickInterval& lhs,
|
||||
const TickInterval& rhs) {
|
||||
return TickInterval(lhs.interval_ - rhs.interval_);
|
||||
}
|
||||
|
||||
inline TickInterval operator-(const TickTime& lhs, const TickTime& rhs) {
|
||||
return TickInterval(lhs.ticks_ - rhs.ticks_);
|
||||
}
|
||||
|
||||
inline TickTime operator+(const TickTime lhs, const int64_t ticks) {
|
||||
TickTime time = lhs;
|
||||
time.ticks_ += ticks;
|
||||
return time;
|
||||
}
|
||||
|
||||
inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) {
|
||||
return lhs.interval_ > rhs.interval_;
|
||||
}
|
||||
|
||||
inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) {
|
||||
return lhs.interval_ <= rhs.interval_;
|
||||
}
|
||||
|
||||
inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) {
|
||||
return lhs.interval_ <= rhs.interval_;
|
||||
}
|
||||
|
||||
inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) {
|
||||
return lhs.interval_ >= rhs.interval_;
|
||||
}
|
||||
|
||||
inline TickTime::TickTime()
|
||||
: ticks_(0) {
|
||||
}
|
||||
|
||||
inline TickTime::TickTime(int64_t ticks)
|
||||
: ticks_(ticks) {
|
||||
}
|
||||
|
||||
inline TickTime TickTime::Now() {
|
||||
if (use_fake_clock_)
|
||||
return TickTime(fake_ticks_);
|
||||
else
|
||||
return TickTime(QueryOsForTicks());
|
||||
}
|
||||
|
||||
inline int64_t TickTime::MillisecondTimestamp() {
|
||||
int64_t ticks = TickTime::Now().Ticks();
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (ticks * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
return ticks;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ticks / 1000000LL;
|
||||
#else
|
||||
return ticks / 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int64_t TickTime::MicrosecondTimestamp() {
|
||||
int64_t ticks = TickTime::Now().Ticks();
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (ticks * 1000) / (qpfreq.QuadPart / 1000);
|
||||
#else
|
||||
return ticks * 1000LL;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ticks / 1000LL;
|
||||
#else
|
||||
return ticks;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int64_t TickTime::Ticks() const {
|
||||
return ticks_;
|
||||
}
|
||||
|
||||
inline int64_t TickTime::MillisecondsToTicks(const int64_t ms) {
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (qpfreq.QuadPart * ms) / 1000;
|
||||
#else
|
||||
return ms;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ms * 1000000LL;
|
||||
#else
|
||||
return ms * 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int64_t TickTime::TicksToMilliseconds(const int64_t ticks) {
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (ticks * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
return ticks;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ticks / 1000000LL;
|
||||
#else
|
||||
return ticks / 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline TickTime& TickTime::operator+=(const int64_t& ticks) {
|
||||
ticks_ += ticks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TickInterval::TickInterval() : interval_(0) {
|
||||
}
|
||||
|
||||
inline TickInterval::TickInterval(const int64_t interval)
|
||||
: interval_(interval) {
|
||||
}
|
||||
|
||||
inline int64_t TickInterval::Milliseconds() const {
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (interval_ * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
// interval_ is in ms
|
||||
return interval_;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
// interval_ is in ns
|
||||
return interval_ / 1000000;
|
||||
#else
|
||||
// interval_ is usecs
|
||||
return interval_ / 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int64_t TickInterval::Microseconds() const {
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (interval_ * 1000000) / qpfreq.QuadPart;
|
||||
#else
|
||||
// interval_ is in ms
|
||||
return interval_ * 1000LL;
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
// interval_ is in ns
|
||||
return interval_ / 1000;
|
||||
#else
|
||||
// interval_ is usecs
|
||||
return interval_;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) {
|
||||
interval_ += rhs.interval_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) {
|
||||
interval_ -= rhs.interval_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INTERFACE_TIMESTAMP_EXTRAPOLATOR_H_
|
||||
#define SYSTEM_WRAPPERS_INTERFACE_TIMESTAMP_EXTRAPOLATOR_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
|
||||
class TimestampExtrapolator
|
||||
{
|
||||
public:
|
||||
explicit TimestampExtrapolator(int64_t start_ms);
|
||||
~TimestampExtrapolator();
|
||||
void Update(int64_t tMs, uint32_t ts90khz);
|
||||
int64_t ExtrapolateLocalTime(uint32_t timestamp90khz);
|
||||
void Reset(int64_t start_ms);
|
||||
|
||||
private:
|
||||
void CheckForWrapArounds(uint32_t ts90khz);
|
||||
bool DelayChangeDetection(double error);
|
||||
RWLockWrapper* _rwLock;
|
||||
double _w[2];
|
||||
double _P[2][2];
|
||||
int64_t _startMs;
|
||||
int64_t _prevMs;
|
||||
uint32_t _firstTimestamp;
|
||||
int32_t _wrapArounds;
|
||||
int64_t _prevUnwrappedTimestamp;
|
||||
int64_t _prevWrapTimestamp;
|
||||
const double _lambda;
|
||||
bool _firstAfterReset;
|
||||
uint32_t _packetCount;
|
||||
const uint32_t _startUpFilterDelayInPackets;
|
||||
|
||||
double _detectorAccumulatorPos;
|
||||
double _detectorAccumulatorNeg;
|
||||
const double _alarmThreshold;
|
||||
const double _accDrift;
|
||||
const double _accMaxError;
|
||||
const double _P11;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INTERFACE_TIMESTAMP_EXTRAPOLATOR_H_
|
92
jni/webrtc/system_wrappers/interface/trace.h
Normal file
92
jni/webrtc/system_wrappers/interface/trace.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*
|
||||
* System independent wrapper for logging runtime information to file.
|
||||
* Note: All log messages will be written to the same trace file.
|
||||
* Note: If too many messages are written to file there will be a build up of
|
||||
* messages. Apply filtering to avoid that.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if defined(WEBRTC_RESTRICT_LOGGING)
|
||||
// Disable all TRACE macros. The LOG macro is still functional.
|
||||
#define WEBRTC_TRACE true ? (void) 0 : Trace::Add
|
||||
#else
|
||||
#define WEBRTC_TRACE Trace::Add
|
||||
#endif
|
||||
|
||||
class Trace {
|
||||
public:
|
||||
// The length of the trace text preceeding the log message.
|
||||
static const int kBoilerplateLength;
|
||||
// The position of the timestamp text within a trace.
|
||||
static const int kTimestampPosition;
|
||||
// The length of the timestamp (without "delta" field).
|
||||
static const int kTimestampLength;
|
||||
|
||||
// Increments the reference count to the trace.
|
||||
static void CreateTrace();
|
||||
// Decrements the reference count to the trace.
|
||||
static void ReturnTrace();
|
||||
// Note: any instance that writes to the trace file should increment and
|
||||
// decrement the reference count on construction and destruction,
|
||||
// respectively.
|
||||
|
||||
// Specifies what type of messages should be written to the trace file. The
|
||||
// filter parameter is a bitmask where each message type is enumerated by the
|
||||
// TraceLevel enumerator. TODO(hellner): why is the TraceLevel enumerator not
|
||||
// defined in this file?
|
||||
static void set_level_filter(uint32_t filter) { level_filter_ = filter; }
|
||||
|
||||
// Returns what type of messages are written to the trace file.
|
||||
static uint32_t level_filter() { return level_filter_; }
|
||||
|
||||
// Sets the file name. If add_file_counter is false the same file will be
|
||||
// reused when it fills up. If it's true a new file with incremented name
|
||||
// will be used.
|
||||
static int32_t SetTraceFile(const char* file_name,
|
||||
const bool add_file_counter = false);
|
||||
|
||||
// Returns the name of the file that the trace is currently writing to.
|
||||
static int32_t TraceFile(char file_name[1024]);
|
||||
|
||||
// Registers callback to receive trace messages.
|
||||
// TODO(hellner): Why not use OutStream instead? Why is TraceCallback not
|
||||
// defined in this file?
|
||||
static int32_t SetTraceCallback(TraceCallback* callback);
|
||||
|
||||
// Adds a trace message for writing to file. The message is put in a queue
|
||||
// for writing to file whenever possible for performance reasons. I.e. there
|
||||
// is a crash it is possible that the last, vital logs are not logged yet.
|
||||
// level is the type of message to log. If that type of messages is
|
||||
// filtered it will not be written to file. module is an identifier for what
|
||||
// part of the code the message is coming.
|
||||
// id is an identifier that should be unique for that set of classes that
|
||||
// are associated (e.g. all instances owned by an engine).
|
||||
// msg and the ellipsis are the same as e.g. sprintf.
|
||||
// TODO(hellner) Why is TraceModule not defined in this file?
|
||||
static void Add(const TraceLevel level,
|
||||
const TraceModule module,
|
||||
const int32_t id,
|
||||
const char* msg, ...);
|
||||
|
||||
private:
|
||||
static uint32_t level_filter_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
912
jni/webrtc/system_wrappers/interface/trace_event.h
Normal file
912
jni/webrtc/system_wrappers/interface/trace_event.h
Normal file
@@ -0,0 +1,912 @@
|
||||
// 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 under third_party_mods/chromium or at:
|
||||
// http://src.chromium.org/svn/trunk/src/LICENSE
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_EVENT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_EVENT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_tracer.h"
|
||||
|
||||
#if defined(TRACE_EVENT0)
|
||||
#error "Another copy of trace_event.h has already been included."
|
||||
#endif
|
||||
|
||||
// Extracted from Chromium's src/base/debug/trace_event.h.
|
||||
|
||||
// This header is designed to give you trace_event macros without specifying
|
||||
// how the events actually get collected and stored. If you need to expose trace
|
||||
// event to some other universe, you can copy-and-paste this file,
|
||||
// implement the TRACE_EVENT_API macros, and do any other necessary fixup for
|
||||
// the target platform. The end result is that multiple libraries can funnel
|
||||
// events through to a shared trace event collector.
|
||||
|
||||
// Trace events are for tracking application performance and resource usage.
|
||||
// Macros are provided to track:
|
||||
// Begin and end of function calls
|
||||
// Counters
|
||||
//
|
||||
// Events are issued against categories. Whereas LOG's
|
||||
// categories are statically defined, TRACE categories are created
|
||||
// implicitly with a string. For example:
|
||||
// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
|
||||
//
|
||||
// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
|
||||
// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
|
||||
// doSomethingCostly()
|
||||
// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
|
||||
// Note: our tools can't always determine the correct BEGIN/END pairs unless
|
||||
// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
|
||||
// need them to be in separate scopes.
|
||||
//
|
||||
// A common use case is to trace entire function scopes. This
|
||||
// issues a trace BEGIN and END automatically:
|
||||
// void doSomethingCostly() {
|
||||
// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Additional parameters can be associated with an event:
|
||||
// void doSomethingCostly2(int howMuch) {
|
||||
// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
|
||||
// "howMuch", howMuch);
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The trace system will automatically add to this information the
|
||||
// current process id, thread id, and a timestamp in microseconds.
|
||||
//
|
||||
// To trace an asynchronous procedure such as an IPC send/receive, use
|
||||
// ASYNC_BEGIN and ASYNC_END:
|
||||
// [single threaded sender code]
|
||||
// static int send_count = 0;
|
||||
// ++send_count;
|
||||
// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
|
||||
// Send(new MyMessage(send_count));
|
||||
// [receive code]
|
||||
// void OnMyMessage(send_count) {
|
||||
// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
|
||||
// }
|
||||
// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
|
||||
// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
|
||||
// Pointers can be used for the ID parameter, and they will be mangled
|
||||
// internally so that the same pointer on two different processes will not
|
||||
// match. For example:
|
||||
// class MyTracedClass {
|
||||
// public:
|
||||
// MyTracedClass() {
|
||||
// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
|
||||
// }
|
||||
// ~MyTracedClass() {
|
||||
// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Trace event also supports counters, which is a way to track a quantity
|
||||
// as it varies over time. Counters are created with the following macro:
|
||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
|
||||
//
|
||||
// Counters are process-specific. The macro itself can be issued from any
|
||||
// thread, however.
|
||||
//
|
||||
// Sometimes, you want to track two counters at once. You can do this with two
|
||||
// counter macros:
|
||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
|
||||
// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
|
||||
// Or you can do it with a combined macro:
|
||||
// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
|
||||
// "bytesPinned", g_myCounterValue[0],
|
||||
// "bytesAllocated", g_myCounterValue[1]);
|
||||
// This indicates to the tracing UI that these counters should be displayed
|
||||
// in a single graph, as a summed area chart.
|
||||
//
|
||||
// Since counters are in a global namespace, you may want to disembiguate with a
|
||||
// unique ID, by using the TRACE_COUNTER_ID* variations.
|
||||
//
|
||||
// By default, trace collection is compiled in, but turned off at runtime.
|
||||
// Collecting trace data is the responsibility of the embedding
|
||||
// application. In Chrome's case, navigating to about:tracing will turn on
|
||||
// tracing and display data collected across all active processes.
|
||||
//
|
||||
//
|
||||
// Memory scoping note:
|
||||
// Tracing copies the pointers, not the string content, of the strings passed
|
||||
// in for category, name, and arg_names. Thus, the following code will
|
||||
// cause problems:
|
||||
// char* str = strdup("impprtantName");
|
||||
// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
|
||||
// free(str); // Trace system now has dangling pointer
|
||||
//
|
||||
// To avoid this issue with the |name| and |arg_name| parameters, use the
|
||||
// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
|
||||
// Notes: The category must always be in a long-lived char* (i.e. static const).
|
||||
// The |arg_values|, when used, are always deep copied with the _COPY
|
||||
// macros.
|
||||
//
|
||||
// When are string argument values copied:
|
||||
// const char* arg_values are only referenced by default:
|
||||
// TRACE_EVENT1("category", "name",
|
||||
// "arg1", "literal string is only referenced");
|
||||
// Use TRACE_STR_COPY to force copying of a const char*:
|
||||
// TRACE_EVENT1("category", "name",
|
||||
// "arg1", TRACE_STR_COPY("string will be copied"));
|
||||
// std::string arg_values are always copied:
|
||||
// TRACE_EVENT1("category", "name",
|
||||
// "arg1", std::string("string will be copied"));
|
||||
//
|
||||
//
|
||||
// Thread Safety:
|
||||
// Thread safety is provided by methods defined in event_tracer.h. See the file
|
||||
// for details.
|
||||
|
||||
|
||||
// By default, const char* argument values are assumed to have long-lived scope
|
||||
// and will not be copied. Use this macro to force a const char* to be copied.
|
||||
#define TRACE_STR_COPY(str) \
|
||||
webrtc::trace_event_internal::TraceStringWithCopy(str)
|
||||
|
||||
// By default, uint64 ID argument values are not mangled with the Process ID in
|
||||
// TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling.
|
||||
#define TRACE_ID_MANGLE(id) \
|
||||
webrtc::trace_event_internal::TraceID::ForceMangle(id)
|
||||
|
||||
// Records a pair of begin and end events called "name" for the current
|
||||
// scope, with 0, 1 or 2 associated arguments. If the category is not
|
||||
// enabled, then this does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
|
||||
#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
|
||||
// Same as TRACE_EVENT except that they are not included in official builds.
|
||||
#ifdef OFFICIAL_BUILD
|
||||
#define UNSHIPPED_TRACE_EVENT0(category, name) (void)0
|
||||
#define UNSHIPPED_TRACE_EVENT1(category, name, arg1_name, arg1_val) (void)0
|
||||
#define UNSHIPPED_TRACE_EVENT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) (void)0
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT0(category, name) (void)0
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
(void)0
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) (void)0
|
||||
#else
|
||||
#define UNSHIPPED_TRACE_EVENT0(category, name) \
|
||||
TRACE_EVENT0(category, name)
|
||||
#define UNSHIPPED_TRACE_EVENT1(category, name, arg1_name, arg1_val) \
|
||||
TRACE_EVENT1(category, name, arg1_name, arg1_val)
|
||||
#define UNSHIPPED_TRACE_EVENT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT0(category, name) \
|
||||
TRACE_EVENT_INSTANT0(category, name)
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val)
|
||||
#define UNSHIPPED_TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
#endif
|
||||
|
||||
// Records a single event called "name" immediately, with 0, 1 or 2
|
||||
// associated arguments. If the category is not enabled, then this
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_INSTANT0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_INSTANT0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
|
||||
// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
|
||||
// associated arguments. If the category is not enabled, then this
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_BEGIN0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_BEGIN0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
|
||||
// Records a single END event for "name" immediately. If the category
|
||||
// is not enabled, then this does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_EVENT_END0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_END0(category, name) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val)
|
||||
|
||||
// Records the value of a counter called "name" immediately. Value
|
||||
// must be representable as a 32 bit integer.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_COUNTER1(category, name, value) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, \
|
||||
"value", static_cast<int>(value))
|
||||
#define TRACE_COPY_COUNTER1(category, name, value) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, \
|
||||
"value", static_cast<int>(value))
|
||||
|
||||
// Records the values of a multi-parted counter called "name" immediately.
|
||||
// The UI will treat value1 and value2 as parts of a whole, displaying their
|
||||
// values as a stacked-bar chart.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
|
||||
value2_name, value2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, TRACE_EVENT_FLAG_NONE, \
|
||||
value1_name, static_cast<int>(value1_val), \
|
||||
value2_name, static_cast<int>(value2_val))
|
||||
#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
|
||||
value2_name, value2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, TRACE_EVENT_FLAG_COPY, \
|
||||
value1_name, static_cast<int>(value1_val), \
|
||||
value2_name, static_cast<int>(value2_val))
|
||||
|
||||
// Records the value of a counter called "name" immediately. Value
|
||||
// must be representable as a 32 bit integer.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to disambiguate counters with the same name. It must either
|
||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
|
||||
// will be xored with a hash of the process ID so that the same pointer on
|
||||
// two different processes will not collide.
|
||||
#define TRACE_COUNTER_ID1(category, name, id, value) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
"value", static_cast<int>(value))
|
||||
#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
"value", static_cast<int>(value))
|
||||
|
||||
// Records the values of a multi-parted counter called "name" immediately.
|
||||
// The UI will treat value1 and value2 as parts of a whole, displaying their
|
||||
// values as a stacked-bar chart.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to disambiguate counters with the same name. It must either
|
||||
// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
|
||||
// will be xored with a hash of the process ID so that the same pointer on
|
||||
// two different processes will not collide.
|
||||
#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
|
||||
value2_name, value2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
value1_name, static_cast<int>(value1_val), \
|
||||
value2_name, static_cast<int>(value2_val))
|
||||
#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
|
||||
value2_name, value2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
value1_name, static_cast<int>(value1_val), \
|
||||
value2_name, static_cast<int>(value2_val))
|
||||
|
||||
|
||||
// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
|
||||
// associated arguments. If the category is not enabled, then this
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
|
||||
// events are considered to match if their category, name and id values all
|
||||
// match. |id| must either be a pointer or an integer value up to 64 bits. If
|
||||
// it's a pointer, the bits will be xored with a hash of the process ID so
|
||||
// that the same pointer on two different processes will not collide.
|
||||
// An asynchronous operation can consist of multiple phases. The first phase is
|
||||
// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
|
||||
// ASYNC_STEP macros. When the operation completes, call ASYNC_END.
|
||||
// An ASYNC trace typically occur on a single thread (if not, they will only be
|
||||
// drawn on the thread defined in the ASYNC_BEGIN event), but all events in that
|
||||
// operation must use the same |name| and |id|. Each event can have its own
|
||||
// args.
|
||||
#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
|
||||
// Records a single ASYNC_STEP event for |step| immediately. If the category
|
||||
// is not enabled, then this does nothing. The |name| and |id| must match the
|
||||
// ASYNC_BEGIN event above. The |step| param identifies this step within the
|
||||
// async event. This should be called at the beginning of the next phase of an
|
||||
// asynchronous operation.
|
||||
#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
|
||||
#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
|
||||
#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
|
||||
arg1_name, arg1_val)
|
||||
|
||||
// Records a single ASYNC_END event for "name" immediately. If the category
|
||||
// is not enabled, then this does nothing.
|
||||
#define TRACE_EVENT_ASYNC_END0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
|
||||
|
||||
// Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2
|
||||
// associated arguments. If the category is not enabled, then this
|
||||
// does nothing.
|
||||
// - category and name strings must have application lifetime (statics or
|
||||
// literals). They may not include " chars.
|
||||
// - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW
|
||||
// events are considered to match if their category, name and id values all
|
||||
// match. |id| must either be a pointer or an integer value up to 64 bits. If
|
||||
// it's a pointer, the bits will be xored with a hash of the process ID so
|
||||
// that the same pointer on two different processes will not collide.
|
||||
// FLOW events are different from ASYNC events in how they are drawn by the
|
||||
// tracing UI. A FLOW defines asynchronous data flow, such as posting a task
|
||||
// (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be
|
||||
// drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar
|
||||
// to ASYNC, a FLOW can consist of multiple phases. The first phase is defined
|
||||
// by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP
|
||||
// macros. When the operation completes, call FLOW_END. An async operation can
|
||||
// span threads and processes, but all events in that operation must use the
|
||||
// same |name| and |id|. Each event can have its own args.
|
||||
#define TRACE_EVENT_FLOW_BEGIN0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_FLOW_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_FLOW_BEGIN2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_FLOW_BEGIN0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_FLOW_BEGIN1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_FLOW_BEGIN2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
|
||||
// Records a single FLOW_STEP event for |step| immediately. If the category
|
||||
// is not enabled, then this does nothing. The |name| and |id| must match the
|
||||
// FLOW_BEGIN event above. The |step| param identifies this step within the
|
||||
// async event. This should be called at the beginning of the next phase of an
|
||||
// asynchronous operation.
|
||||
#define TRACE_EVENT_FLOW_STEP0(category, name, id, step) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
|
||||
#define TRACE_EVENT_FLOW_STEP1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_FLOW_STEP0(category, name, id, step) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
|
||||
#define TRACE_EVENT_COPY_FLOW_STEP1(category, name, id, step, \
|
||||
arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
|
||||
arg1_name, arg1_val)
|
||||
|
||||
// Records a single FLOW_END event for "name" immediately. If the category
|
||||
// is not enabled, then this does nothing.
|
||||
#define TRACE_EVENT_FLOW_END0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE)
|
||||
#define TRACE_EVENT_FLOW_END1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_FLOW_END2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_NONE, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
#define TRACE_EVENT_COPY_FLOW_END0(category, name, id) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY)
|
||||
#define TRACE_EVENT_COPY_FLOW_END1(category, name, id, arg1_name, arg1_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val)
|
||||
#define TRACE_EVENT_COPY_FLOW_END2(category, name, id, arg1_name, arg1_val, \
|
||||
arg2_name, arg2_val) \
|
||||
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
|
||||
category, name, id, TRACE_EVENT_FLAG_COPY, \
|
||||
arg1_name, arg1_val, arg2_name, arg2_val)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation specific tracing API definitions.
|
||||
|
||||
// Get a pointer to the enabled state of the given trace category. Only
|
||||
// long-lived literal strings should be given as the category name. The returned
|
||||
// pointer can be held permanently in a local static for example. If the
|
||||
// unsigned char is non-zero, tracing is enabled. If tracing is enabled,
|
||||
// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
|
||||
// between the load of the tracing state and the call to
|
||||
// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
|
||||
// for best performance when tracing is disabled.
|
||||
// const unsigned char*
|
||||
// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
|
||||
#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
|
||||
webrtc::EventTracer::GetCategoryEnabled
|
||||
|
||||
// Add a trace event to the platform tracing system.
|
||||
// void TRACE_EVENT_API_ADD_TRACE_EVENT(
|
||||
// char phase,
|
||||
// const unsigned char* category_enabled,
|
||||
// const char* name,
|
||||
// unsigned long long id,
|
||||
// int num_args,
|
||||
// const char** arg_names,
|
||||
// const unsigned char* arg_types,
|
||||
// const unsigned long long* arg_values,
|
||||
// unsigned char flags)
|
||||
#define TRACE_EVENT_API_ADD_TRACE_EVENT webrtc::EventTracer::AddTraceEvent
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Implementation detail: trace event macros create temporary variables
|
||||
// to keep instrumentation overhead low. These macros give each temporary
|
||||
// variable a unique name based on the line number to prevent name collissions.
|
||||
#define INTERNAL_TRACE_EVENT_UID3(a,b) \
|
||||
trace_event_unique_##a##b
|
||||
#define INTERNAL_TRACE_EVENT_UID2(a,b) \
|
||||
INTERNAL_TRACE_EVENT_UID3(a,b)
|
||||
#define INTERNAL_TRACE_EVENT_UID(name_prefix) \
|
||||
INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
|
||||
|
||||
// Implementation detail: internal macro to create static category.
|
||||
#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
|
||||
static const unsigned char* INTERNAL_TRACE_EVENT_UID(catstatic) = 0; \
|
||||
if (!INTERNAL_TRACE_EVENT_UID(catstatic)) { \
|
||||
INTERNAL_TRACE_EVENT_UID(catstatic) = \
|
||||
TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); \
|
||||
}
|
||||
|
||||
// Implementation detail: internal macro to create static category and add
|
||||
// event if the category is enabled.
|
||||
#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
|
||||
do { \
|
||||
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
|
||||
if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
|
||||
webrtc::trace_event_internal::AddTraceEvent( \
|
||||
phase, INTERNAL_TRACE_EVENT_UID(catstatic), name, \
|
||||
webrtc::trace_event_internal::kNoEventId, flags, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Implementation detail: internal macro to create static category and add begin
|
||||
// event if the category is enabled. Also adds the end event when the scope
|
||||
// ends.
|
||||
#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
|
||||
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
|
||||
webrtc::trace_event_internal::TraceEndOnScopeClose \
|
||||
INTERNAL_TRACE_EVENT_UID(profileScope); \
|
||||
if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
|
||||
webrtc::trace_event_internal::AddTraceEvent( \
|
||||
TRACE_EVENT_PHASE_BEGIN, \
|
||||
INTERNAL_TRACE_EVENT_UID(catstatic), \
|
||||
name, webrtc::trace_event_internal::kNoEventId, \
|
||||
TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
|
||||
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
|
||||
INTERNAL_TRACE_EVENT_UID(catstatic), name); \
|
||||
}
|
||||
|
||||
// Implementation detail: internal macro to create static category and add
|
||||
// event if the category is enabled.
|
||||
#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
|
||||
...) \
|
||||
do { \
|
||||
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
|
||||
if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
|
||||
unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
|
||||
webrtc::trace_event_internal::TraceID trace_event_trace_id( \
|
||||
id, &trace_event_flags); \
|
||||
webrtc::trace_event_internal::AddTraceEvent( \
|
||||
phase, INTERNAL_TRACE_EVENT_UID(catstatic), \
|
||||
name, trace_event_trace_id.data(), trace_event_flags, \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Notes regarding the following definitions:
|
||||
// New values can be added and propagated to third party libraries, but existing
|
||||
// definitions must never be changed, because third party libraries may use old
|
||||
// definitions.
|
||||
|
||||
// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
|
||||
#define TRACE_EVENT_PHASE_BEGIN ('B')
|
||||
#define TRACE_EVENT_PHASE_END ('E')
|
||||
#define TRACE_EVENT_PHASE_INSTANT ('I')
|
||||
#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
|
||||
#define TRACE_EVENT_PHASE_ASYNC_STEP ('T')
|
||||
#define TRACE_EVENT_PHASE_ASYNC_END ('F')
|
||||
#define TRACE_EVENT_PHASE_FLOW_BEGIN ('s')
|
||||
#define TRACE_EVENT_PHASE_FLOW_STEP ('t')
|
||||
#define TRACE_EVENT_PHASE_FLOW_END ('f')
|
||||
#define TRACE_EVENT_PHASE_METADATA ('M')
|
||||
#define TRACE_EVENT_PHASE_COUNTER ('C')
|
||||
|
||||
// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
|
||||
#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
|
||||
#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
|
||||
#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
|
||||
#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
|
||||
|
||||
// Type values for identifying types in the TraceValue union.
|
||||
#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
|
||||
#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
|
||||
#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
|
||||
#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
|
||||
#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
|
||||
#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
|
||||
#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
|
||||
|
||||
namespace webrtc {
|
||||
namespace trace_event_internal {
|
||||
|
||||
// Specify these values when the corresponding argument of AddTraceEvent is not
|
||||
// used.
|
||||
const int kZeroNumArgs = 0;
|
||||
const unsigned long long kNoEventId = 0;
|
||||
|
||||
// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
|
||||
// are mangled with the Process ID so that they are unlikely to collide when the
|
||||
// same pointer is used on different processes.
|
||||
class TraceID {
|
||||
public:
|
||||
class ForceMangle {
|
||||
public:
|
||||
explicit ForceMangle(unsigned long long id) : data_(id) {}
|
||||
explicit ForceMangle(unsigned long id) : data_(id) {}
|
||||
explicit ForceMangle(unsigned int id) : data_(id) {}
|
||||
explicit ForceMangle(unsigned short id) : data_(id) {}
|
||||
explicit ForceMangle(unsigned char id) : data_(id) {}
|
||||
explicit ForceMangle(long long id)
|
||||
: data_(static_cast<unsigned long long>(id)) {}
|
||||
explicit ForceMangle(long id)
|
||||
: data_(static_cast<unsigned long long>(id)) {}
|
||||
explicit ForceMangle(int id)
|
||||
: data_(static_cast<unsigned long long>(id)) {}
|
||||
explicit ForceMangle(short id)
|
||||
: data_(static_cast<unsigned long long>(id)) {}
|
||||
explicit ForceMangle(signed char id)
|
||||
: data_(static_cast<unsigned long long>(id)) {}
|
||||
|
||||
unsigned long long data() const { return data_; }
|
||||
|
||||
private:
|
||||
unsigned long long data_;
|
||||
};
|
||||
|
||||
explicit TraceID(const void* id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(
|
||||
reinterpret_cast<unsigned long>(id))) {
|
||||
*flags |= TRACE_EVENT_FLAG_MANGLE_ID;
|
||||
}
|
||||
explicit TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) {
|
||||
*flags |= TRACE_EVENT_FLAG_MANGLE_ID;
|
||||
}
|
||||
explicit TraceID(unsigned long long id, unsigned char* flags)
|
||||
: data_(id) { (void)flags; }
|
||||
explicit TraceID(unsigned long id, unsigned char* flags)
|
||||
: data_(id) { (void)flags; }
|
||||
explicit TraceID(unsigned int id, unsigned char* flags)
|
||||
: data_(id) { (void)flags; }
|
||||
explicit TraceID(unsigned short id, unsigned char* flags)
|
||||
: data_(id) { (void)flags; }
|
||||
explicit TraceID(unsigned char id, unsigned char* flags)
|
||||
: data_(id) { (void)flags; }
|
||||
explicit TraceID(long long id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(id)) { (void)flags; }
|
||||
explicit TraceID(long id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(id)) { (void)flags; }
|
||||
explicit TraceID(int id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(id)) { (void)flags; }
|
||||
explicit TraceID(short id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(id)) { (void)flags; }
|
||||
explicit TraceID(signed char id, unsigned char* flags)
|
||||
: data_(static_cast<unsigned long long>(id)) { (void)flags; }
|
||||
|
||||
unsigned long long data() const { return data_; }
|
||||
|
||||
private:
|
||||
unsigned long long data_;
|
||||
};
|
||||
|
||||
// Simple union to store various types as unsigned long long.
|
||||
union TraceValueUnion {
|
||||
bool as_bool;
|
||||
unsigned long long as_uint;
|
||||
long long as_int;
|
||||
double as_double;
|
||||
const void* as_pointer;
|
||||
const char* as_string;
|
||||
};
|
||||
|
||||
// Simple container for const char* that should be copied instead of retained.
|
||||
class TraceStringWithCopy {
|
||||
public:
|
||||
explicit TraceStringWithCopy(const char* str) : str_(str) {}
|
||||
operator const char* () const { return str_; }
|
||||
private:
|
||||
const char* str_;
|
||||
};
|
||||
|
||||
// Define SetTraceValue for each allowed type. It stores the type and
|
||||
// value in the return arguments. This allows this API to avoid declaring any
|
||||
// structures so that it is portable to third_party libraries.
|
||||
#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
|
||||
union_member, \
|
||||
value_type_id) \
|
||||
static inline void SetTraceValue(actual_type arg, \
|
||||
unsigned char* type, \
|
||||
unsigned long long* value) { \
|
||||
TraceValueUnion type_value; \
|
||||
type_value.union_member = arg; \
|
||||
*type = value_type_id; \
|
||||
*value = type_value.as_uint; \
|
||||
}
|
||||
// Simpler form for int types that can be safely casted.
|
||||
#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
|
||||
value_type_id) \
|
||||
static inline void SetTraceValue(actual_type arg, \
|
||||
unsigned char* type, \
|
||||
unsigned long long* value) { \
|
||||
*type = value_type_id; \
|
||||
*value = static_cast<unsigned long long>(arg); \
|
||||
}
|
||||
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
|
||||
TRACE_VALUE_TYPE_POINTER)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
|
||||
TRACE_VALUE_TYPE_STRING)
|
||||
INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
|
||||
TRACE_VALUE_TYPE_COPY_STRING)
|
||||
|
||||
#undef INTERNAL_DECLARE_SET_TRACE_VALUE
|
||||
#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
|
||||
|
||||
// std::string version of SetTraceValue so that trace arguments can be strings.
|
||||
static inline void SetTraceValue(const std::string& arg,
|
||||
unsigned char* type,
|
||||
unsigned long long* value) {
|
||||
TraceValueUnion type_value;
|
||||
type_value.as_string = arg.c_str();
|
||||
*type = TRACE_VALUE_TYPE_COPY_STRING;
|
||||
*value = type_value.as_uint;
|
||||
}
|
||||
|
||||
// These AddTraceEvent template functions are defined here instead of in the
|
||||
// macro, because the arg_values could be temporary objects, such as
|
||||
// std::string. In order to store pointers to the internal c_str and pass
|
||||
// through to the tracing API, the arg_values must live throughout
|
||||
// these procedures.
|
||||
|
||||
static inline void AddTraceEvent(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
unsigned char flags) {
|
||||
TRACE_EVENT_API_ADD_TRACE_EVENT(
|
||||
phase, category_enabled, name, id,
|
||||
kZeroNumArgs, NULL, NULL, NULL,
|
||||
flags);
|
||||
}
|
||||
|
||||
template<class ARG1_TYPE>
|
||||
static inline void AddTraceEvent(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
unsigned char flags,
|
||||
const char* arg1_name,
|
||||
const ARG1_TYPE& arg1_val) {
|
||||
const int num_args = 1;
|
||||
unsigned char arg_types[1];
|
||||
unsigned long long arg_values[1];
|
||||
SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
|
||||
TRACE_EVENT_API_ADD_TRACE_EVENT(
|
||||
phase, category_enabled, name, id,
|
||||
num_args, &arg1_name, arg_types, arg_values,
|
||||
flags);
|
||||
}
|
||||
|
||||
template<class ARG1_TYPE, class ARG2_TYPE>
|
||||
static inline void AddTraceEvent(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
unsigned char flags,
|
||||
const char* arg1_name,
|
||||
const ARG1_TYPE& arg1_val,
|
||||
const char* arg2_name,
|
||||
const ARG2_TYPE& arg2_val) {
|
||||
const int num_args = 2;
|
||||
const char* arg_names[2] = { arg1_name, arg2_name };
|
||||
unsigned char arg_types[2];
|
||||
unsigned long long arg_values[2];
|
||||
SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
|
||||
SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
|
||||
TRACE_EVENT_API_ADD_TRACE_EVENT(
|
||||
phase, category_enabled, name, id,
|
||||
num_args, arg_names, arg_types, arg_values,
|
||||
flags);
|
||||
}
|
||||
|
||||
// Used by TRACE_EVENTx macro. Do not use directly.
|
||||
class TraceEndOnScopeClose {
|
||||
public:
|
||||
// Note: members of data_ intentionally left uninitialized. See Initialize.
|
||||
TraceEndOnScopeClose() : p_data_(NULL) {}
|
||||
~TraceEndOnScopeClose() {
|
||||
if (p_data_)
|
||||
AddEventIfEnabled();
|
||||
}
|
||||
|
||||
void Initialize(const unsigned char* category_enabled,
|
||||
const char* name) {
|
||||
data_.category_enabled = category_enabled;
|
||||
data_.name = name;
|
||||
p_data_ = &data_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Add the end event if the category is still enabled.
|
||||
void AddEventIfEnabled() {
|
||||
// Only called when p_data_ is non-null.
|
||||
if (*p_data_->category_enabled) {
|
||||
TRACE_EVENT_API_ADD_TRACE_EVENT(
|
||||
TRACE_EVENT_PHASE_END,
|
||||
p_data_->category_enabled,
|
||||
p_data_->name, kNoEventId,
|
||||
kZeroNumArgs, NULL, NULL, NULL,
|
||||
TRACE_EVENT_FLAG_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
// This Data struct workaround is to avoid initializing all the members
|
||||
// in Data during construction of this object, since this object is always
|
||||
// constructed, even when tracing is disabled. If the members of Data were
|
||||
// members of this class instead, compiler warnings occur about potential
|
||||
// uninitialized accesses.
|
||||
struct Data {
|
||||
const unsigned char* category_enabled;
|
||||
const char* name;
|
||||
};
|
||||
Data* p_data_;
|
||||
Data data_;
|
||||
};
|
||||
|
||||
} // namespace trace_event_internal
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_EVENT_H_
|
57
jni/webrtc/system_wrappers/interface/utf_util_win.h
Normal file
57
jni/webrtc/system_wrappers/interface/utf_util_win.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Conversion functions for UTF-8 and UTF-16 strings on Windows.
|
||||
// Duplicated from talk/base/win32.h.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_UTF_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_UTF_UTIL_H_
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
inline std::wstring ToUtf16(const char* utf8, size_t len) {
|
||||
int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len),
|
||||
NULL, 0);
|
||||
scoped_ptr<wchar_t[]> ws(new wchar_t[len16]);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len), ws.get(),
|
||||
len16);
|
||||
return std::wstring(ws.get(), len16);
|
||||
}
|
||||
|
||||
inline std::wstring ToUtf16(const std::string& str) {
|
||||
return ToUtf16(str.data(), str.length());
|
||||
}
|
||||
|
||||
inline std::string ToUtf8(const wchar_t* wide, size_t len) {
|
||||
int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len),
|
||||
NULL, 0, NULL, NULL);
|
||||
scoped_ptr<char[]> ns(new char[len8]);
|
||||
::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len), ns.get(), len8,
|
||||
NULL, NULL);
|
||||
return std::string(ns.get(), len8);
|
||||
}
|
||||
|
||||
inline std::string ToUtf8(const wchar_t* wide) {
|
||||
return ToUtf8(wide, wcslen(wide));
|
||||
}
|
||||
|
||||
inline std::string ToUtf8(const std::wstring& wstr) {
|
||||
return ToUtf8(wstr.data(), wstr.length());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WIN32
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_UTF_UTIL_H_
|
68
jni/webrtc/system_wrappers/source/Android.mk
Normal file
68
jni/webrtc/system_wrappers/source/Android.mk
Normal file
@@ -0,0 +1,68 @@
|
||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include $(LOCAL_PATH)/../../../android-webrtc.mk
|
||||
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_MODULE := libwebrtc_system_wrappers
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
LOCAL_SRC_FILES := \
|
||||
cpu_features_android.c \
|
||||
sort.cc \
|
||||
aligned_malloc.cc \
|
||||
atomic32_posix.cc \
|
||||
condition_variable.cc \
|
||||
cpu_features.cc \
|
||||
cpu_info.cc \
|
||||
critical_section.cc \
|
||||
event.cc \
|
||||
event_tracer.cc \
|
||||
file_impl.cc \
|
||||
rw_lock.cc \
|
||||
thread.cc \
|
||||
trace_impl.cc \
|
||||
condition_variable_posix.cc \
|
||||
critical_section_posix.cc \
|
||||
event_posix.cc \
|
||||
rtp_to_ntp.cc \
|
||||
sleep.cc \
|
||||
thread_posix.cc \
|
||||
tick_util.cc \
|
||||
timestamp_extrapolator.cc \
|
||||
trace_posix.cc \
|
||||
rw_lock_generic.cc \
|
||||
rw_lock_posix.cc \
|
||||
logging.cc
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
$(MY_WEBRTC_COMMON_DEFS)
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/../.. \
|
||||
$(LOCAL_PATH)/../interface \
|
||||
$(LOCAL_PATH)/spreadsortlib \
|
||||
$(LOCAL_PATH)/../../..
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libdl \
|
||||
libstlport
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := cpufeatures
|
||||
|
||||
ifndef NDK_ROOT
|
||||
include external/stlport/libstlport.mk
|
||||
endif
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
$(call import-module,android/cpufeatures)
|
6
jni/webrtc/system_wrappers/source/OWNERS
Normal file
6
jni/webrtc/system_wrappers/source/OWNERS
Normal file
@@ -0,0 +1,6 @@
|
||||
per-file *.isolate=kjellander@webrtc.org
|
||||
|
||||
# These are for the common case of adding or renaming files. If you're doing
|
||||
# structural changes, please get a review from a reviewer in this file.
|
||||
per-file *.gyp=*
|
||||
per-file *.gypi=*
|
100
jni/webrtc/system_wrappers/source/aligned_malloc.cc
Normal file
100
jni/webrtc/system_wrappers/source/aligned_malloc.cc
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/aligned_malloc.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Reference on memory alignment:
|
||||
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
|
||||
namespace webrtc {
|
||||
|
||||
uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
|
||||
// The pointer should be aligned with |alignment| bytes. The - 1 guarantees
|
||||
// that it is aligned towards the closest higher (right) address.
|
||||
return (start_pos + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Alignment must be an integer power of two.
|
||||
bool ValidAlignment(size_t alignment) {
|
||||
if (!alignment) {
|
||||
return false;
|
||||
}
|
||||
return (alignment & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
void* GetRightAlign(const void* pointer, size_t alignment) {
|
||||
if (!pointer) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
|
||||
return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
|
||||
}
|
||||
|
||||
void* AlignedMalloc(size_t size, size_t alignment) {
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The memory is aligned towards the lowest address that so only
|
||||
// alignment - 1 bytes needs to be allocated.
|
||||
// A pointer to the start of the memory must be stored so that it can be
|
||||
// retreived for deletion, ergo the sizeof(uintptr_t).
|
||||
void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
|
||||
if (memory_pointer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Aligning after the sizeof(uintptr_t) bytes will leave room for the header
|
||||
// in the same memory block.
|
||||
uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
align_start_pos += sizeof(uintptr_t);
|
||||
uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
|
||||
void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
|
||||
|
||||
// Store the address to the beginning of the memory just before the aligned
|
||||
// memory.
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
void* header_pointer = reinterpret_cast<void*>(header_pos);
|
||||
uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
|
||||
|
||||
return aligned_pointer;
|
||||
}
|
||||
|
||||
void AlignedFree(void* mem_block) {
|
||||
if (mem_block == NULL) {
|
||||
return;
|
||||
}
|
||||
uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
|
||||
// Read out the address of the AlignedMemory struct from the header.
|
||||
uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
|
||||
void* memory_start = reinterpret_cast<void*>(memory_start_pos);
|
||||
free(memory_start);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
82
jni/webrtc/system_wrappers/source/aligned_malloc_unittest.cc
Normal file
82
jni/webrtc/system_wrappers/source/aligned_malloc_unittest.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/aligned_malloc.h"
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Returns true if |size| and |alignment| are valid combinations.
|
||||
bool CorrectUsage(size_t size, size_t alignment) {
|
||||
scoped_ptr<char, AlignedFreeDeleter> scoped(
|
||||
static_cast<char*>(AlignedMalloc(size, alignment)));
|
||||
if (scoped.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
const uintptr_t scoped_address = reinterpret_cast<uintptr_t> (scoped.get());
|
||||
return 0u == scoped_address % alignment;
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, GetRightAlign) {
|
||||
const size_t size = 100;
|
||||
const size_t alignment = 32;
|
||||
const size_t left_misalignment = 1;
|
||||
scoped_ptr<char, AlignedFreeDeleter> scoped(
|
||||
static_cast<char*>(AlignedMalloc(size, alignment)));
|
||||
EXPECT_TRUE(scoped.get() != NULL);
|
||||
const uintptr_t aligned_address = reinterpret_cast<uintptr_t> (scoped.get());
|
||||
const uintptr_t misaligned_address = aligned_address - left_misalignment;
|
||||
const char* misaligned_ptr = reinterpret_cast<const char*>(
|
||||
misaligned_address);
|
||||
const char* realigned_ptr = GetRightAlign(misaligned_ptr, alignment);
|
||||
EXPECT_EQ(scoped.get(), realigned_ptr);
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, IncorrectSize) {
|
||||
const size_t incorrect_size = 0;
|
||||
const size_t alignment = 64;
|
||||
EXPECT_FALSE(CorrectUsage(incorrect_size, alignment));
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, IncorrectAlignment) {
|
||||
const size_t size = 100;
|
||||
const size_t incorrect_alignment = 63;
|
||||
EXPECT_FALSE(CorrectUsage(size, incorrect_alignment));
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, AlignTo2Bytes) {
|
||||
size_t size = 100;
|
||||
size_t alignment = 2;
|
||||
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, AlignTo32Bytes) {
|
||||
size_t size = 100;
|
||||
size_t alignment = 32;
|
||||
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||
}
|
||||
|
||||
TEST(AlignedMalloc, AlignTo128Bytes) {
|
||||
size_t size = 100;
|
||||
size_t alignment = 128;
|
||||
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
49
jni/webrtc/system_wrappers/source/atomic32_mac.cc
Normal file
49
jni/webrtc/system_wrappers/source/atomic32_mac.cc
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Atomic32::Atomic32(int32_t initial_value)
|
||||
: value_(initial_value) {
|
||||
assert(Is32bitAligned());
|
||||
}
|
||||
|
||||
Atomic32::~Atomic32() {
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator++() {
|
||||
return OSAtomicIncrement32Barrier(&value_);
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator--() {
|
||||
return OSAtomicDecrement32Barrier(&value_);
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator+=(int32_t value) {
|
||||
return OSAtomicAdd32Barrier(value, &value_);
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator-=(int32_t value) {
|
||||
return OSAtomicAdd32Barrier(-value, &value_);
|
||||
}
|
||||
|
||||
bool Atomic32::CompareExchange(int32_t new_value, int32_t compare_value) {
|
||||
return OSAtomicCompareAndSwap32Barrier(compare_value, new_value, &value_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
53
jni/webrtc/system_wrappers/source/atomic32_posix.cc
Normal file
53
jni/webrtc/system_wrappers/source/atomic32_posix.cc
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Atomic32::Atomic32(int32_t initial_value)
|
||||
: value_(initial_value) {
|
||||
assert(Is32bitAligned());
|
||||
}
|
||||
|
||||
Atomic32::~Atomic32() {
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator++() {
|
||||
return __sync_fetch_and_add(&value_, 1) + 1;
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator--() {
|
||||
return __sync_fetch_and_sub(&value_, 1) - 1;
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator+=(int32_t value) {
|
||||
int32_t return_value = __sync_fetch_and_add(&value_, value);
|
||||
return_value += value;
|
||||
return return_value;
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator-=(int32_t value) {
|
||||
int32_t return_value = __sync_fetch_and_sub(&value_, value);
|
||||
return_value -= value;
|
||||
return return_value;
|
||||
}
|
||||
|
||||
bool Atomic32::CompareExchange(int32_t new_value, int32_t compare_value) {
|
||||
return __sync_bool_compare_and_swap(&value_, compare_value, new_value);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
61
jni/webrtc/system_wrappers/source/atomic32_win.cc
Normal file
61
jni/webrtc/system_wrappers/source/atomic32_win.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/system_wrappers/interface/compile_assert.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Atomic32::Atomic32(int32_t initial_value)
|
||||
: value_(initial_value) {
|
||||
COMPILE_ASSERT(sizeof(value_) == sizeof(LONG),
|
||||
counter_variable_is_the_expected_size);
|
||||
assert(Is32bitAligned());
|
||||
}
|
||||
|
||||
Atomic32::~Atomic32() {
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator++() {
|
||||
return static_cast<int32_t>(InterlockedIncrement(
|
||||
reinterpret_cast<volatile LONG*>(&value_)));
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator--() {
|
||||
return static_cast<int32_t>(InterlockedDecrement(
|
||||
reinterpret_cast<volatile LONG*>(&value_)));
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator+=(int32_t value) {
|
||||
return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&value_),
|
||||
value);
|
||||
}
|
||||
|
||||
int32_t Atomic32::operator-=(int32_t value) {
|
||||
return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&value_),
|
||||
-value);
|
||||
}
|
||||
|
||||
bool Atomic32::CompareExchange(int32_t new_value, int32_t compare_value) {
|
||||
const LONG old_value = InterlockedCompareExchange(
|
||||
reinterpret_cast<volatile LONG*>(&value_),
|
||||
new_value,
|
||||
compare_value);
|
||||
|
||||
// If the old value and the compare value is the same an exchange happened.
|
||||
return (old_value == compare_value);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
304
jni/webrtc/system_wrappers/source/clock.cc
Normal file
304
jni/webrtc/system_wrappers/source/clock.cc
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows needs to be included before mmsystem.h
|
||||
#include <Windows.h>
|
||||
#include <WinSock.h>
|
||||
#include <MMSystem.h>
|
||||
#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const double kNtpFracPerMs = 4.294967296E6;
|
||||
|
||||
int64_t Clock::NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) {
|
||||
const double ntp_frac_ms = static_cast<double>(ntp_frac) / kNtpFracPerMs;
|
||||
return 1000 * static_cast<int64_t>(ntp_secs) +
|
||||
static_cast<int64_t>(ntp_frac_ms + 0.5);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
struct reference_point {
|
||||
FILETIME file_time;
|
||||
LARGE_INTEGER counterMS;
|
||||
};
|
||||
|
||||
struct WindowsHelpTimer {
|
||||
volatile LONG _timeInMs;
|
||||
volatile LONG _numWrapTimeInMs;
|
||||
reference_point _ref_point;
|
||||
|
||||
volatile LONG _sync_flag;
|
||||
};
|
||||
|
||||
void Synchronize(WindowsHelpTimer* help_timer) {
|
||||
const LONG start_value = 0;
|
||||
const LONG new_value = 1;
|
||||
const LONG synchronized_value = 2;
|
||||
|
||||
LONG compare_flag = new_value;
|
||||
while (help_timer->_sync_flag == start_value) {
|
||||
const LONG new_value = 1;
|
||||
compare_flag = InterlockedCompareExchange(
|
||||
&help_timer->_sync_flag, new_value, start_value);
|
||||
}
|
||||
if (compare_flag != start_value) {
|
||||
// This thread was not the one that incremented the sync flag.
|
||||
// Block until synchronization finishes.
|
||||
while (compare_flag != synchronized_value) {
|
||||
::Sleep(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Only the synchronizing thread gets here so this part can be
|
||||
// considered single threaded.
|
||||
|
||||
// set timer accuracy to 1 ms
|
||||
timeBeginPeriod(1);
|
||||
FILETIME ft0 = { 0, 0 },
|
||||
ft1 = { 0, 0 };
|
||||
//
|
||||
// Spin waiting for a change in system time. Get the matching
|
||||
// performance counter value for that time.
|
||||
//
|
||||
::GetSystemTimeAsFileTime(&ft0);
|
||||
do {
|
||||
::GetSystemTimeAsFileTime(&ft1);
|
||||
|
||||
help_timer->_ref_point.counterMS.QuadPart = ::timeGetTime();
|
||||
::Sleep(0);
|
||||
} while ((ft0.dwHighDateTime == ft1.dwHighDateTime) &&
|
||||
(ft0.dwLowDateTime == ft1.dwLowDateTime));
|
||||
help_timer->_ref_point.file_time = ft1;
|
||||
timeEndPeriod(1);
|
||||
}
|
||||
|
||||
void get_time(WindowsHelpTimer* help_timer, FILETIME& current_time) {
|
||||
// we can't use query performance counter due to speed stepping
|
||||
DWORD t = timeGetTime();
|
||||
// NOTE: we have a missmatch in sign between _timeInMs(LONG) and
|
||||
// (DWORD) however we only use it here without +- etc
|
||||
volatile LONG* timeInMsPtr = &help_timer->_timeInMs;
|
||||
// Make sure that we only inc wrapper once.
|
||||
DWORD old = InterlockedExchange(timeInMsPtr, t);
|
||||
if(old > t) {
|
||||
// wrap
|
||||
help_timer->_numWrapTimeInMs++;
|
||||
}
|
||||
LARGE_INTEGER elapsedMS;
|
||||
elapsedMS.HighPart = help_timer->_numWrapTimeInMs;
|
||||
elapsedMS.LowPart = t;
|
||||
|
||||
elapsedMS.QuadPart = elapsedMS.QuadPart -
|
||||
help_timer->_ref_point.counterMS.QuadPart;
|
||||
|
||||
// Translate to 100-nanoseconds intervals (FILETIME resolution)
|
||||
// and add to reference FILETIME to get current FILETIME.
|
||||
ULARGE_INTEGER filetime_ref_as_ul;
|
||||
|
||||
filetime_ref_as_ul.HighPart =
|
||||
help_timer->_ref_point.file_time.dwHighDateTime;
|
||||
filetime_ref_as_ul.LowPart =
|
||||
help_timer->_ref_point.file_time.dwLowDateTime;
|
||||
filetime_ref_as_ul.QuadPart +=
|
||||
(ULONGLONG)((elapsedMS.QuadPart)*1000*10);
|
||||
|
||||
// Copy to result
|
||||
current_time.dwHighDateTime = filetime_ref_as_ul.HighPart;
|
||||
current_time.dwLowDateTime = filetime_ref_as_ul.LowPart;
|
||||
}
|
||||
#endif
|
||||
|
||||
class RealTimeClock : public Clock {
|
||||
// Return a timestamp in milliseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMilliseconds() const OVERRIDE {
|
||||
return TickTime::MillisecondTimestamp();
|
||||
}
|
||||
|
||||
// Return a timestamp in microseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
virtual int64_t TimeInMicroseconds() const OVERRIDE {
|
||||
return TickTime::MicrosecondTimestamp();
|
||||
}
|
||||
|
||||
// Retrieve an NTP absolute timestamp in seconds and fractions of a second.
|
||||
virtual void CurrentNtp(uint32_t& seconds,
|
||||
uint32_t& fractions) const OVERRIDE {
|
||||
timeval tv = CurrentTimeVal();
|
||||
double microseconds_in_seconds;
|
||||
Adjust(tv, &seconds, µseconds_in_seconds);
|
||||
fractions = static_cast<uint32_t>(
|
||||
microseconds_in_seconds * kMagicNtpFractionalUnit + 0.5);
|
||||
}
|
||||
|
||||
// Retrieve an NTP absolute timestamp in milliseconds.
|
||||
virtual int64_t CurrentNtpInMilliseconds() const OVERRIDE {
|
||||
timeval tv = CurrentTimeVal();
|
||||
uint32_t seconds;
|
||||
double microseconds_in_seconds;
|
||||
Adjust(tv, &seconds, µseconds_in_seconds);
|
||||
return 1000 * static_cast<int64_t>(seconds) +
|
||||
static_cast<int64_t>(1000.0 * microseconds_in_seconds + 0.5);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual timeval CurrentTimeVal() const = 0;
|
||||
|
||||
static void Adjust(const timeval& tv, uint32_t* adjusted_s,
|
||||
double* adjusted_us_in_s) {
|
||||
*adjusted_s = tv.tv_sec + kNtpJan1970;
|
||||
*adjusted_us_in_s = tv.tv_usec / 1e6;
|
||||
|
||||
if (*adjusted_us_in_s >= 1) {
|
||||
*adjusted_us_in_s -= 1;
|
||||
++*adjusted_s;
|
||||
} else if (*adjusted_us_in_s < -1) {
|
||||
*adjusted_us_in_s += 1;
|
||||
--*adjusted_s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
class WindowsRealTimeClock : public RealTimeClock {
|
||||
public:
|
||||
WindowsRealTimeClock(WindowsHelpTimer* helpTimer)
|
||||
: _helpTimer(helpTimer) {}
|
||||
|
||||
virtual ~WindowsRealTimeClock() {}
|
||||
|
||||
protected:
|
||||
virtual timeval CurrentTimeVal() const OVERRIDE {
|
||||
const uint64_t FILETIME_1970 = 0x019db1ded53e8000;
|
||||
|
||||
FILETIME StartTime;
|
||||
uint64_t Time;
|
||||
struct timeval tv;
|
||||
|
||||
// We can't use query performance counter since they can change depending on
|
||||
// speed stepping.
|
||||
get_time(_helpTimer, StartTime);
|
||||
|
||||
Time = (((uint64_t) StartTime.dwHighDateTime) << 32) +
|
||||
(uint64_t) StartTime.dwLowDateTime;
|
||||
|
||||
// Convert the hecto-nano second time to tv format.
|
||||
Time -= FILETIME_1970;
|
||||
|
||||
tv.tv_sec = (uint32_t)(Time / (uint64_t)10000000);
|
||||
tv.tv_usec = (uint32_t)((Time % (uint64_t)10000000) / 10);
|
||||
return tv;
|
||||
}
|
||||
|
||||
WindowsHelpTimer* _helpTimer;
|
||||
};
|
||||
|
||||
#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
|
||||
class UnixRealTimeClock : public RealTimeClock {
|
||||
public:
|
||||
UnixRealTimeClock() {}
|
||||
|
||||
virtual ~UnixRealTimeClock() {}
|
||||
|
||||
protected:
|
||||
virtual timeval CurrentTimeVal() const OVERRIDE {
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
tz.tz_minuteswest = 0;
|
||||
tz.tz_dsttime = 0;
|
||||
gettimeofday(&tv, &tz);
|
||||
return tv;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Keeps the global state for the Windows implementation of RtpRtcpClock.
|
||||
// Note that this is a POD. Only PODs are allowed to have static storage
|
||||
// duration according to the Google Style guide.
|
||||
//
|
||||
// Note that on Windows, GetSystemTimeAsFileTime has poorer (up to 15 ms)
|
||||
// resolution than the media timers, hence the WindowsHelpTimer context
|
||||
// object and Synchronize API to sync the two.
|
||||
//
|
||||
// We only sync up once, which means that on Windows, our realtime clock
|
||||
// wont respond to system time/date changes without a program restart.
|
||||
// TODO(henrike): We should probably call sync more often to catch
|
||||
// drift and time changes for parity with other platforms.
|
||||
|
||||
static WindowsHelpTimer *SyncGlobalHelpTimer() {
|
||||
static WindowsHelpTimer global_help_timer = {0, 0, {{ 0, 0}, 0}, 0};
|
||||
Synchronize(&global_help_timer);
|
||||
return &global_help_timer;
|
||||
}
|
||||
#endif
|
||||
|
||||
Clock* Clock::GetRealTimeClock() {
|
||||
#if defined(_WIN32)
|
||||
static WindowsRealTimeClock clock(SyncGlobalHelpTimer());
|
||||
return &clock;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
static UnixRealTimeClock clock;
|
||||
return &clock;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
SimulatedClock::SimulatedClock(int64_t initial_time_us)
|
||||
: time_us_(initial_time_us), lock_(RWLockWrapper::CreateRWLock()) {
|
||||
}
|
||||
|
||||
SimulatedClock::~SimulatedClock() {
|
||||
}
|
||||
|
||||
int64_t SimulatedClock::TimeInMilliseconds() const {
|
||||
ReadLockScoped synchronize(*lock_);
|
||||
return (time_us_ + 500) / 1000;
|
||||
}
|
||||
|
||||
int64_t SimulatedClock::TimeInMicroseconds() const {
|
||||
ReadLockScoped synchronize(*lock_);
|
||||
return time_us_;
|
||||
}
|
||||
|
||||
void SimulatedClock::CurrentNtp(uint32_t& seconds, uint32_t& fractions) const {
|
||||
int64_t now_ms = TimeInMilliseconds();
|
||||
seconds = (now_ms / 1000) + kNtpJan1970;
|
||||
fractions =
|
||||
static_cast<uint32_t>((now_ms % 1000) * kMagicNtpFractionalUnit / 1000);
|
||||
}
|
||||
|
||||
int64_t SimulatedClock::CurrentNtpInMilliseconds() const {
|
||||
return TimeInMilliseconds() + 1000 * static_cast<int64_t>(kNtpJan1970);
|
||||
}
|
||||
|
||||
void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) {
|
||||
AdvanceTimeMicroseconds(1000 * milliseconds);
|
||||
}
|
||||
|
||||
void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) {
|
||||
WriteLockScoped synchronize(*lock_);
|
||||
time_us_ += microseconds;
|
||||
}
|
||||
|
||||
}; // namespace webrtc
|
27
jni/webrtc/system_wrappers/source/clock_unittest.cc
Normal file
27
jni/webrtc/system_wrappers/source/clock_unittest.cc
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(ClockTest, NtpTime) {
|
||||
Clock* clock = Clock::GetRealTimeClock();
|
||||
uint32_t seconds;
|
||||
uint32_t fractions;
|
||||
clock->CurrentNtp(seconds, fractions);
|
||||
int64_t milliseconds = clock->CurrentNtpInMilliseconds();
|
||||
EXPECT_GT(milliseconds / 1000, kNtpJan1970);
|
||||
EXPECT_GE(milliseconds, Clock::NtpToMs(seconds, fractions));
|
||||
EXPECT_NEAR(milliseconds, Clock::NtpToMs(seconds, fractions), 5);
|
||||
}
|
||||
} // namespace webrtc
|
41
jni/webrtc/system_wrappers/source/condition_variable.cc
Normal file
41
jni/webrtc/system_wrappers/source/condition_variable.cc
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/condition_variable_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableWrapper::CreateConditionVariable() {
|
||||
#if defined(_WIN32)
|
||||
// Try to create native condition variable implementation.
|
||||
ConditionVariableWrapper* ret_val = ConditionVariableNativeWin::Create();
|
||||
if (!ret_val) {
|
||||
// Native condition variable implementation does not exist. Create generic
|
||||
// condition variable based on events.
|
||||
ret_val = new ConditionVariableEventWin();
|
||||
}
|
||||
return ret_val;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ConditionVariablePosix::Create();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
Source:
|
||||
http://www1.cse.wustl.edu/~schmidt/ACE-copying.html
|
||||
|
||||
License:
|
||||
Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM),
|
||||
and CoSMIC(TM)
|
||||
|
||||
ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to
|
||||
as "DOC software") are copyrighted by Douglas C. Schmidt and his research
|
||||
group at Washington University, University of California, Irvine, and
|
||||
Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC
|
||||
software is open-source, freely available software, you are free to use,
|
||||
modify, copy, and distribute--perpetually and irrevocably--the DOC software
|
||||
source code and object code produced from the source, as well as copy and
|
||||
distribute modified versions of this software. You must, however, include this
|
||||
copyright statement along with any code built using DOC software that you
|
||||
release. No copyright statement needs to be provided if you just ship binary
|
||||
executables of your software products.
|
||||
You can use DOC software in commercial and/or binary software releases and are
|
||||
under no obligation to redistribute any of your source code that is built
|
||||
using DOC software. Note, however, that you may not misappropriate the DOC
|
||||
software code, such as copyrighting it yourself or claiming authorship of the
|
||||
DOC software code, in a way that will prevent DOC software from being
|
||||
distributed freely using an open-source development model. You needn't inform
|
||||
anyone that you're using DOC software in your software, though we encourage
|
||||
you to let us know so we can promote your project in the DOC software success
|
||||
stories.
|
||||
|
||||
The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC
|
||||
Group at the Institute for Software Integrated Systems (ISIS) and the Center
|
||||
for Distributed Object Computing of Washington University, St. Louis for the
|
||||
development of open-source software as part of the open-source software
|
||||
community. Submissions are provided by the submitter ``as is'' with no
|
||||
warranties whatsoever, including any warranty of merchantability,
|
||||
noninfringement of third party intellectual property, or fitness for any
|
||||
particular purpose. In no event shall the submitter be liable for any direct,
|
||||
indirect, special, exemplary, punitive, or consequential damages, including
|
||||
without limitation, lost profits, even if advised of the possibility of such
|
||||
damages. Likewise, DOC software is provided as is with no warranties of any
|
||||
kind, including the warranties of design, merchantability, and fitness for a
|
||||
particular purpose, noninfringement, or arising from a course of dealing,
|
||||
usage or trade practice. Washington University, UC Irvine, Vanderbilt
|
||||
University, their employees, and students shall have no liability with respect
|
||||
to the infringement of copyrights, trade secrets or any patents by DOC
|
||||
software or any part thereof. Moreover, in no event will Washington
|
||||
University, UC Irvine, or Vanderbilt University, their employees, or students
|
||||
be liable for any lost revenue or profits or other special, indirect and
|
||||
consequential damages.
|
||||
|
||||
DOC software is provided with no support and without any obligation on the
|
||||
part of Washington University, UC Irvine, Vanderbilt University, their
|
||||
employees, or students to assist in its use, correction, modification, or
|
||||
enhancement. A number of companies around the world provide commercial support
|
||||
for DOC software, however. DOC software is Y2K-compliant, as long as the
|
||||
underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant
|
||||
with the new US daylight savings rule passed by Congress as "The Energy Policy
|
||||
Act of 2005," which established new daylight savings times (DST) rules for the
|
||||
United States that expand DST as of March 2007. Since DOC software obtains
|
||||
time/date and calendaring information from operating systems users will not be
|
||||
affected by the new DST rules as long as they upgrade their operating systems
|
||||
accordingly.
|
||||
|
||||
The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington
|
||||
University, UC Irvine, and Vanderbilt University, may not be used to endorse
|
||||
or promote products or services derived from this source without express
|
||||
written permission from Washington University, UC Irvine, or Vanderbilt
|
||||
University. This license grants no permission to call products or services
|
||||
derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM),
|
||||
nor does it grant permission for the name Washington University, UC Irvine, or
|
||||
Vanderbilt University to appear in their names.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code contain modifications to the original source code
|
||||
* which can be found here:
|
||||
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
|
||||
* Modifications:
|
||||
* 1) Dynamic detection of native support for condition variables.
|
||||
* 2) Use of WebRTC defined types and classes. Renaming of some functions.
|
||||
* 3) Introduction of a second event for wake all functionality. This prevents
|
||||
* a thread from spinning on the same condition variable, preventing other
|
||||
* threads from waking up.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableEventWin::ConditionVariableEventWin() : eventID_(WAKEALL_0) {
|
||||
memset(&num_waiters_[0], 0, sizeof(num_waiters_));
|
||||
|
||||
InitializeCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKE] = CreateEvent(NULL, // no security attributes
|
||||
FALSE, // auto-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
}
|
||||
|
||||
ConditionVariableEventWin::~ConditionVariableEventWin() {
|
||||
CloseHandle(events_[WAKE]);
|
||||
CloseHandle(events_[WAKEALL_1]);
|
||||
CloseHandle(events_[WAKEALL_0]);
|
||||
|
||||
DeleteCriticalSection(&num_waiters_crit_sect_);
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Get the eventID for the event that will be triggered by next
|
||||
// WakeAll() call and start waiting for it.
|
||||
const EventWakeUpType eventID =
|
||||
(WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
++(num_waiters_[eventID]);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&crit_sect);
|
||||
LeaveCriticalSection(&cs->crit);
|
||||
HANDLE events[2];
|
||||
events[0] = events_[WAKE];
|
||||
events[1] = events_[eventID];
|
||||
const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
|
||||
events,
|
||||
FALSE, // Wait for either.
|
||||
max_time_in_ms);
|
||||
|
||||
const bool ret_val = (result != WAIT_TIMEOUT);
|
||||
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
--(num_waiters_[eventID]);
|
||||
|
||||
// Last waiter should only be true for WakeAll(). WakeAll() correspond
|
||||
// to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
|
||||
const bool last_waiter = (result == WAIT_OBJECT_0 + 1) &&
|
||||
(num_waiters_[eventID] == 0);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (last_waiter) {
|
||||
// Reset/unset the WakeAll() event since all threads have been
|
||||
// released.
|
||||
ResetEvent(events_[eventID]);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&cs->crit);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::Wake() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
const bool have_waiters = (num_waiters_[WAKEALL_0] > 0) ||
|
||||
(num_waiters_[WAKEALL_1] > 0);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[WAKE]);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::WakeAll() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Update current WakeAll() event
|
||||
eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
// Trigger current event
|
||||
const EventWakeUpType eventID = eventID_;
|
||||
const bool have_waiters = num_waiters_[eventID] > 0;
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[eventID]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ConditionVariableEventWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
ConditionVariableEventWin();
|
||||
virtual ~ConditionVariableEventWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
enum EventWakeUpType {
|
||||
WAKEALL_0 = 0,
|
||||
WAKEALL_1 = 1,
|
||||
WAKE = 2,
|
||||
EVENT_COUNT = 3
|
||||
};
|
||||
|
||||
unsigned int num_waiters_[2];
|
||||
EventWakeUpType eventID_;
|
||||
CRITICAL_SECTION num_waiters_crit_sect_;
|
||||
HANDLE events_[EVENT_COUNT];
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static HMODULE library = NULL;
|
||||
static bool win_support_condition_variables_primitive = false;
|
||||
|
||||
PInitializeConditionVariable PInitializeConditionVariable_;
|
||||
PSleepConditionVariableCS PSleepConditionVariableCS_;
|
||||
PWakeConditionVariable PWakeConditionVariable_;
|
||||
PWakeAllConditionVariable PWakeAllConditionVariable_;
|
||||
|
||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
ConditionVariableNativeWin::ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableNativeWin::~ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableNativeWin::Create() {
|
||||
ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::Init() {
|
||||
if (!library) {
|
||||
// Native implementation is supported on Vista+.
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
// TODO(henrike): this code results in an attempt to load the above dll
|
||||
// every time the previous attempt failed. Only try to load once.
|
||||
if (library) {
|
||||
// TODO(henrike): not thread safe as reading and writing to library is not
|
||||
// serialized. Fix.
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
PInitializeConditionVariable_ =
|
||||
(PInitializeConditionVariable) GetProcAddress(
|
||||
library, "InitializeConditionVariable");
|
||||
PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
|
||||
library, "SleepConditionVariableCS");
|
||||
PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
|
||||
library, "WakeConditionVariable");
|
||||
PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
|
||||
library, "WakeAllConditionVariable");
|
||||
|
||||
if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
|
||||
&& PWakeConditionVariable_ && PWakeAllConditionVariable_) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded native condition variables");
|
||||
win_support_condition_variables_primitive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!win_support_condition_variables_primitive) {
|
||||
return false;
|
||||
}
|
||||
PInitializeConditionVariable_(&condition_variable_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&crit_sect);
|
||||
BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_,
|
||||
&(cs->crit), max_time_in_ms);
|
||||
return ret_val != 0;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::Wake() {
|
||||
PWakeConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::WakeAll() {
|
||||
PWakeAllConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if !defined CONDITION_VARIABLE_INIT
|
||||
typedef struct RTL_CONDITION_VARIABLE_ {
|
||||
void* Ptr;
|
||||
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
||||
|
||||
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
||||
#endif
|
||||
|
||||
typedef void (WINAPI* PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI* PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI* PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI* PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
class ConditionVariableNativeWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
static ConditionVariableWrapper* Create();
|
||||
virtual ~ConditionVariableNativeWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
ConditionVariableNativeWin();
|
||||
|
||||
bool Init();
|
||||
|
||||
CONDITION_VARIABLE condition_variable_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
132
jni/webrtc/system_wrappers/source/condition_variable_posix.cc
Normal file
132
jni/webrtc/system_wrappers/source/condition_variable_posix.cc
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/condition_variable_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/system_wrappers/source/critical_section_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableWrapper* ConditionVariablePosix::Create() {
|
||||
ConditionVariablePosix* ptr = new ConditionVariablePosix;
|
||||
if (!ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int error = ptr->Construct();
|
||||
if (error) {
|
||||
delete ptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ConditionVariablePosix::ConditionVariablePosix() {
|
||||
}
|
||||
|
||||
int ConditionVariablePosix::Construct() {
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
pthread_cond_init(&cond_, NULL);
|
||||
#else
|
||||
int result = 0;
|
||||
pthread_condattr_t cond_attr;
|
||||
result = pthread_condattr_init(&cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_cond_init(&cond_, &cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_destroy(&cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConditionVariablePosix::~ConditionVariablePosix() {
|
||||
pthread_cond_destroy(&cond_);
|
||||
}
|
||||
|
||||
void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
||||
&crit_sect);
|
||||
pthread_cond_wait(&cond_, &cs->mutex_);
|
||||
}
|
||||
|
||||
bool ConditionVariablePosix::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_inMS) {
|
||||
const unsigned long INFINITE = 0xFFFFFFFF;
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
#ifndef WEBRTC_LINUX
|
||||
const int MICROSECONDS_PER_MILLISECOND = 1000;
|
||||
#endif
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>(
|
||||
&crit_sect);
|
||||
|
||||
if (max_time_inMS != INFINITE) {
|
||||
timespec ts;
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
#else // WEBRTC_MAC
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
|
||||
#endif
|
||||
|
||||
ts.tv_sec += max_time_inMS / MILLISECONDS_PER_SECOND;
|
||||
ts.tv_nsec +=
|
||||
(max_time_inMS
|
||||
- ((max_time_inMS / MILLISECONDS_PER_SECOND) * MILLISECONDS_PER_SECOND))
|
||||
* NANOSECONDS_PER_MILLISECOND;
|
||||
|
||||
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) {
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
const int res = pthread_cond_timedwait(&cond_, &cs->mutex_, &ts);
|
||||
return (res == ETIMEDOUT) ? false : true;
|
||||
} else {
|
||||
pthread_cond_wait(&cond_, &cs->mutex_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariablePosix::Wake() {
|
||||
pthread_cond_signal(&cond_);
|
||||
}
|
||||
|
||||
void ConditionVariablePosix::WakeAll() {
|
||||
pthread_cond_broadcast(&cond_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
42
jni/webrtc/system_wrappers/source/condition_variable_posix.h
Normal file
42
jni/webrtc/system_wrappers/source/condition_variable_posix.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ConditionVariablePosix : public ConditionVariableWrapper {
|
||||
public:
|
||||
static ConditionVariableWrapper* Create();
|
||||
virtual ~ConditionVariablePosix();
|
||||
|
||||
virtual void SleepCS(CriticalSectionWrapper& crit_sect) OVERRIDE;
|
||||
virtual bool SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) OVERRIDE;
|
||||
virtual void Wake() OVERRIDE;
|
||||
virtual void WakeAll() OVERRIDE;
|
||||
|
||||
private:
|
||||
ConditionVariablePosix();
|
||||
int Construct();
|
||||
|
||||
private:
|
||||
pthread_cond_t cond_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_POSIX_H_
|
191
jni/webrtc/system_wrappers/source/condition_variable_unittest.cc
Normal file
191
jni/webrtc/system_wrappers/source/condition_variable_unittest.cc
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kLongWaitMs = 100 * 1000; // A long time in testing terms
|
||||
const int kShortWaitMs = 2 * 1000; // Long enough for process switches to happen
|
||||
|
||||
// A Baton is one possible control structure one can build using
|
||||
// conditional variables.
|
||||
// A Baton is always held by one and only one active thread - unlike
|
||||
// a lock, it can never be free.
|
||||
// One can pass it or grab it - both calls have timeouts.
|
||||
// Note - a production tool would guard against passing it without
|
||||
// grabbing it first. This one is for testing, so it doesn't.
|
||||
class Baton {
|
||||
public:
|
||||
Baton()
|
||||
: giver_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
cond_var_(ConditionVariableWrapper::CreateConditionVariable()),
|
||||
being_passed_(false),
|
||||
pass_count_(0) {
|
||||
}
|
||||
|
||||
~Baton() {
|
||||
delete giver_sect_;
|
||||
delete crit_sect_;
|
||||
delete cond_var_;
|
||||
}
|
||||
|
||||
// Pass the baton. Returns false if baton is not picked up in |max_msecs|.
|
||||
// Only one process can pass at the same time; this property is
|
||||
// ensured by the |giver_sect_| lock.
|
||||
bool Pass(uint32_t max_msecs) {
|
||||
CriticalSectionScoped cs_giver(giver_sect_);
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
SignalBatonAvailable();
|
||||
const bool result = TakeBatonIfStillFree(max_msecs);
|
||||
if (result) {
|
||||
++pass_count_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Grab the baton. Returns false if baton is not passed.
|
||||
bool Grab(uint32_t max_msecs) {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
return WaitUntilBatonOffered(max_msecs);
|
||||
}
|
||||
|
||||
int PassCount() {
|
||||
// We don't allow polling PassCount() during a Pass()-call since there is
|
||||
// no guarantee that |pass_count_| is incremented until the Pass()-call
|
||||
// finishes. I.e. the Grab()-call may finish before |pass_count_| has been
|
||||
// incremented.
|
||||
// Thus, this function waits on giver_sect_.
|
||||
CriticalSectionScoped cs(giver_sect_);
|
||||
return pass_count_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Wait/Signal forms a classical semaphore on |being_passed_|.
|
||||
// These functions must be called with crit_sect_ held.
|
||||
bool WaitUntilBatonOffered(int timeout_ms) {
|
||||
while (!being_passed_) {
|
||||
if (!cond_var_->SleepCS(*crit_sect_, timeout_ms)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
being_passed_ = false;
|
||||
cond_var_->Wake();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignalBatonAvailable() {
|
||||
assert(!being_passed_);
|
||||
being_passed_ = true;
|
||||
cond_var_->Wake();
|
||||
}
|
||||
|
||||
// Timeout extension: Wait for a limited time for someone else to
|
||||
// take it, and take it if it's not taken.
|
||||
// Returns true if resource is taken by someone else, false
|
||||
// if it is taken back by the caller.
|
||||
// This function must be called with both |giver_sect_| and
|
||||
// |crit_sect_| held.
|
||||
bool TakeBatonIfStillFree(int timeout_ms) {
|
||||
bool not_timeout = true;
|
||||
while (being_passed_ && not_timeout) {
|
||||
not_timeout = cond_var_->SleepCS(*crit_sect_, timeout_ms);
|
||||
// If we're woken up while variable is still held, we may have
|
||||
// gotten a wakeup destined for a grabber thread.
|
||||
// This situation is not treated specially here.
|
||||
}
|
||||
if (!being_passed_) {
|
||||
return true;
|
||||
} else {
|
||||
assert(!not_timeout);
|
||||
being_passed_ = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Lock that ensures that there is only one thread in the active
|
||||
// part of Pass() at a time.
|
||||
// |giver_sect_| must always be acquired before |cond_var_|.
|
||||
CriticalSectionWrapper* giver_sect_;
|
||||
// Lock that protects |being_passed_|.
|
||||
CriticalSectionWrapper* crit_sect_;
|
||||
ConditionVariableWrapper* cond_var_;
|
||||
bool being_passed_;
|
||||
// Statistics information: Number of successfull passes.
|
||||
int pass_count_;
|
||||
};
|
||||
|
||||
// Function that waits on a Baton, and passes it right back.
|
||||
// We expect these calls never to time out.
|
||||
bool WaitingRunFunction(void* obj) {
|
||||
Baton* the_baton = static_cast<Baton*> (obj);
|
||||
EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
|
||||
EXPECT_TRUE(the_baton->Pass(kLongWaitMs));
|
||||
return true;
|
||||
}
|
||||
|
||||
class CondVarTest : public ::testing::Test {
|
||||
public:
|
||||
CondVarTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
thread_ = ThreadWrapper::CreateThread(&WaitingRunFunction,
|
||||
&baton_);
|
||||
unsigned int id = 42;
|
||||
ASSERT_TRUE(thread_->Start(id));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
// We have to wake the thread in order to make it obey the stop order.
|
||||
// But we don't know if the thread has completed the run function, so
|
||||
// we don't know if it will exit before or after the Pass.
|
||||
// Thus, we need to pin it down inside its Run function (between Grab
|
||||
// and Pass).
|
||||
ASSERT_TRUE(baton_.Pass(kShortWaitMs));
|
||||
thread_->SetNotAlive();
|
||||
ASSERT_TRUE(baton_.Grab(kShortWaitMs));
|
||||
ASSERT_TRUE(thread_->Stop());
|
||||
delete thread_;
|
||||
}
|
||||
|
||||
protected:
|
||||
Baton baton_;
|
||||
|
||||
private:
|
||||
ThreadWrapper* thread_;
|
||||
};
|
||||
|
||||
// The SetUp and TearDown functions use condition variables.
|
||||
// This test verifies those pieces in isolation.
|
||||
TEST_F(CondVarTest, InitFunctionsWork) {
|
||||
// All relevant asserts are in the SetUp and TearDown functions.
|
||||
}
|
||||
|
||||
// This test verifies that one can use the baton multiple times.
|
||||
TEST_F(CondVarTest, PassBatonMultipleTimes) {
|
||||
const int kNumberOfRounds = 2;
|
||||
for (int i = 0; i < kNumberOfRounds; ++i) {
|
||||
ASSERT_TRUE(baton_.Pass(kShortWaitMs));
|
||||
ASSERT_TRUE(baton_.Grab(kShortWaitMs));
|
||||
}
|
||||
EXPECT_EQ(2 * kNumberOfRounds, baton_.PassCount());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace webrtc
|
72
jni/webrtc/system_wrappers/source/cpu_features.cc
Normal file
72
jni/webrtc/system_wrappers/source/cpu_features.cc
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Parts of this file derived from Chromium's base/cpu.cc.
|
||||
|
||||
#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
#ifndef _MSC_VER
|
||||
// Intrinsic for "cpuid".
|
||||
#if defined(__pic__) && defined(__i386__)
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile(
|
||||
"mov %%ebx, %%edi\n"
|
||||
"cpuid\n"
|
||||
"xchg %%edi, %%ebx\n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
#else
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile(
|
||||
"cpuid\n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
#endif // WEBRTC_ARCH_X86_FAMILY
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
// Actual feature detection for x86.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
if (feature == kSSE2) {
|
||||
return 0 != (cpu_info[3] & 0x04000000);
|
||||
}
|
||||
if (feature == kSSE3) {
|
||||
return 0 != (cpu_info[2] & 0x00000001);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Default to straight C for other platforms.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfo = GetCPUInfo;
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM = GetCPUInfoNoASM;
|
15
jni/webrtc/system_wrappers/source/cpu_features_android.c
Normal file
15
jni/webrtc/system_wrappers/source/cpu_features_android.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <cpu-features.h>
|
||||
|
||||
uint64_t WebRtc_GetCPUFeaturesARM(void) {
|
||||
return android_getCpuFeatures();
|
||||
}
|
64
jni/webrtc/system_wrappers/source/cpu_info.cc
Normal file
64
jni/webrtc/system_wrappers/source/cpu_info.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/cpu_info.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#else // defined(WEBRTC_LINUX) or defined(WEBRTC_ANDROID)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
uint32_t CpuInfo::number_of_cores_ = 0;
|
||||
|
||||
uint32_t CpuInfo::DetectNumberOfCores() {
|
||||
if (!number_of_cores_) {
|
||||
#if defined(_WIN32)
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
number_of_cores_ = static_cast<uint32_t>(si.dwNumberOfProcessors);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", number_of_cores_);
|
||||
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
|
||||
number_of_cores_ = static_cast<uint32_t>(sysconf(_SC_NPROCESSORS_ONLN));
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", number_of_cores_);
|
||||
|
||||
#elif defined(WEBRTC_MAC)
|
||||
int name[] = {CTL_HW, HW_AVAILCPU};
|
||||
int ncpu;
|
||||
size_t size = sizeof(ncpu);
|
||||
if (0 == sysctl(name, 2, &ncpu, &size, NULL, 0)) {
|
||||
number_of_cores_ = static_cast<uint32_t>(ncpu);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", number_of_cores_);
|
||||
} else {
|
||||
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
||||
"Failed to get number of cores");
|
||||
number_of_cores_ = 1;
|
||||
}
|
||||
#else
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceUtility, -1,
|
||||
"No function to get number of cores");
|
||||
number_of_cores_ = 1;
|
||||
#endif
|
||||
}
|
||||
return number_of_cores_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
28
jni/webrtc/system_wrappers/source/critical_section.cc
Normal file
28
jni/webrtc/system_wrappers/source/critical_section.cc
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/critical_section_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionWrapper* CriticalSectionWrapper::CreateCriticalSection() {
|
||||
#ifdef _WIN32
|
||||
return new CriticalSectionWindows();
|
||||
#else
|
||||
return new CriticalSectionPosix();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
42
jni/webrtc/system_wrappers/source/critical_section_posix.cc
Normal file
42
jni/webrtc/system_wrappers/source/critical_section_posix.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// General note: return values for the various pthread synchronization APIs
|
||||
// are explicitly ignored here. In Chromium, the same thing is done for release.
|
||||
// However, in debugging, failure in these APIs are logged. There is currently
|
||||
// no equivalent to DCHECK_EQ in WebRTC code so this is the best we can do here.
|
||||
// TODO(henrike): add logging when pthread synchronization APIs are failing.
|
||||
|
||||
#include "webrtc/system_wrappers/source/critical_section_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionPosix::CriticalSectionPosix() {
|
||||
pthread_mutexattr_t attr;
|
||||
(void) pthread_mutexattr_init(&attr);
|
||||
(void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
(void) pthread_mutex_init(&mutex_, &attr);
|
||||
}
|
||||
|
||||
CriticalSectionPosix::~CriticalSectionPosix() {
|
||||
(void) pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionPosix::Enter() {
|
||||
(void) pthread_mutex_lock(&mutex_);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionPosix::Leave() {
|
||||
(void) pthread_mutex_unlock(&mutex_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
36
jni/webrtc/system_wrappers/source/critical_section_posix.h
Normal file
36
jni/webrtc/system_wrappers/source/critical_section_posix.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionPosix : public CriticalSectionWrapper {
|
||||
public:
|
||||
CriticalSectionPosix();
|
||||
|
||||
virtual ~CriticalSectionPosix();
|
||||
|
||||
virtual void Enter() OVERRIDE;
|
||||
virtual void Leave() OVERRIDE;
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
friend class ConditionVariablePosix;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
142
jni/webrtc/system_wrappers/source/critical_section_unittest.cc
Normal file
142
jni/webrtc/system_wrappers/source/critical_section_unittest.cc
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/sleep.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Cause a process switch. Needed to avoid depending on
|
||||
// busy-wait in tests.
|
||||
static void SwitchProcess() {
|
||||
// Note - sched_yield has been tried as process switch. This does
|
||||
// not cause a process switch enough of the time for reliability.
|
||||
SleepMs(1);
|
||||
}
|
||||
|
||||
class ProtectedCount {
|
||||
public:
|
||||
explicit ProtectedCount(CriticalSectionWrapper* crit_sect)
|
||||
: crit_sect_(crit_sect),
|
||||
count_(0) {
|
||||
}
|
||||
|
||||
void Increment() {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
++count_;
|
||||
}
|
||||
|
||||
int Count() const {
|
||||
CriticalSectionScoped cs(crit_sect_);
|
||||
return count_;
|
||||
}
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* crit_sect_;
|
||||
int count_;
|
||||
};
|
||||
|
||||
class CritSectTest : public ::testing::Test {
|
||||
public:
|
||||
CritSectTest() {}
|
||||
|
||||
// Waits a number of cycles for the count to reach a given value.
|
||||
// Returns true if the target is reached or passed.
|
||||
bool WaitForCount(int target, ProtectedCount* count) {
|
||||
int loop_counter = 0;
|
||||
// On Posix, this SwitchProcess() needs to be in a loop to make the
|
||||
// test both fast and non-flaky.
|
||||
// With 1 us wait as the switch, up to 7 rounds have been observed.
|
||||
while (count->Count() < target && loop_counter < 100 * target) {
|
||||
++loop_counter;
|
||||
SwitchProcess();
|
||||
}
|
||||
return (count->Count() >= target);
|
||||
}
|
||||
};
|
||||
|
||||
bool LockUnlockThenStopRunFunction(void* obj) {
|
||||
ProtectedCount* the_count = static_cast<ProtectedCount*>(obj);
|
||||
the_count->Increment();
|
||||
return false;
|
||||
}
|
||||
|
||||
TEST_F(CritSectTest, ThreadWakesOnce) NO_THREAD_SAFETY_ANALYSIS {
|
||||
CriticalSectionWrapper* crit_sect =
|
||||
CriticalSectionWrapper::CreateCriticalSection();
|
||||
ProtectedCount count(crit_sect);
|
||||
ThreadWrapper* thread = ThreadWrapper::CreateThread(
|
||||
&LockUnlockThenStopRunFunction, &count);
|
||||
unsigned int id = 42;
|
||||
crit_sect->Enter();
|
||||
ASSERT_TRUE(thread->Start(id));
|
||||
SwitchProcess();
|
||||
// The critical section is of reentrant mode, so this should not release
|
||||
// the lock, even though count.Count() locks and unlocks the critical section
|
||||
// again.
|
||||
// Thus, the thread should not be able to increment the count
|
||||
ASSERT_EQ(0, count.Count());
|
||||
crit_sect->Leave(); // This frees the thread to act.
|
||||
EXPECT_TRUE(WaitForCount(1, &count));
|
||||
EXPECT_TRUE(thread->Stop());
|
||||
delete thread;
|
||||
delete crit_sect;
|
||||
}
|
||||
|
||||
bool LockUnlockRunFunction(void* obj) {
|
||||
ProtectedCount* the_count = static_cast<ProtectedCount*>(obj);
|
||||
the_count->Increment();
|
||||
SwitchProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_F(CritSectTest, ThreadWakesTwice) NO_THREAD_SAFETY_ANALYSIS {
|
||||
CriticalSectionWrapper* crit_sect =
|
||||
CriticalSectionWrapper::CreateCriticalSection();
|
||||
ProtectedCount count(crit_sect);
|
||||
ThreadWrapper* thread = ThreadWrapper::CreateThread(&LockUnlockRunFunction,
|
||||
&count);
|
||||
unsigned int id = 42;
|
||||
crit_sect->Enter(); // Make sure counter stays 0 until we wait for it.
|
||||
ASSERT_TRUE(thread->Start(id));
|
||||
crit_sect->Leave();
|
||||
|
||||
// The thread is capable of grabbing the lock multiple times,
|
||||
// incrementing counter once each time.
|
||||
// It's possible for the count to be incremented by more than 2.
|
||||
EXPECT_TRUE(WaitForCount(2, &count));
|
||||
EXPECT_LE(2, count.Count());
|
||||
|
||||
// The thread does not increment while lock is held.
|
||||
crit_sect->Enter();
|
||||
int count_before = count.Count();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
SwitchProcess();
|
||||
}
|
||||
EXPECT_EQ(count_before, count.Count());
|
||||
crit_sect->Leave();
|
||||
|
||||
thread->SetNotAlive(); // Tell thread to exit once run function finishes.
|
||||
SwitchProcess();
|
||||
EXPECT_TRUE(WaitForCount(count_before + 1, &count));
|
||||
EXPECT_TRUE(thread->Stop());
|
||||
delete thread;
|
||||
delete crit_sect;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace webrtc
|
33
jni/webrtc/system_wrappers/source/critical_section_win.cc
Normal file
33
jni/webrtc/system_wrappers/source/critical_section_win.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionWindows::CriticalSectionWindows() {
|
||||
InitializeCriticalSection(&crit);
|
||||
}
|
||||
|
||||
CriticalSectionWindows::~CriticalSectionWindows() {
|
||||
DeleteCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Enter() {
|
||||
EnterCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Leave() {
|
||||
LeaveCriticalSection(&crit);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
38
jni/webrtc/system_wrappers/source/critical_section_win.h
Normal file
38
jni/webrtc/system_wrappers/source/critical_section_win.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWindows : public CriticalSectionWrapper {
|
||||
public:
|
||||
CriticalSectionWindows();
|
||||
|
||||
virtual ~CriticalSectionWindows();
|
||||
|
||||
virtual void Enter();
|
||||
virtual void Leave();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION crit;
|
||||
|
||||
friend class ConditionVariableEventWin;
|
||||
friend class ConditionVariableNativeWin;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
455
jni/webrtc/system_wrappers/source/data_log.cc
Normal file
455
jni/webrtc/system_wrappers/source/data_log.cc
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/file_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
DataLogImpl::CritSectScopedPtr DataLogImpl::crit_sect_(
|
||||
CriticalSectionWrapper::CreateCriticalSection());
|
||||
|
||||
DataLogImpl* DataLogImpl::instance_ = NULL;
|
||||
|
||||
// A Row contains cells, which are indexed by the column names as std::string.
|
||||
// The string index is treated in a case sensitive way.
|
||||
class Row {
|
||||
public:
|
||||
Row();
|
||||
~Row();
|
||||
|
||||
// Inserts a Container into the cell of the column specified with
|
||||
// column_name.
|
||||
// column_name is treated in a case sensitive way.
|
||||
int InsertCell(const std::string& column_name,
|
||||
const Container* value_container);
|
||||
|
||||
// Converts the value at the column specified by column_name to a string
|
||||
// stored in value_string.
|
||||
// column_name is treated in a case sensitive way.
|
||||
void ToString(const std::string& column_name, std::string* value_string);
|
||||
|
||||
private:
|
||||
// Collection of containers indexed by column name as std::string
|
||||
typedef std::map<std::string, const Container*> CellMap;
|
||||
|
||||
CellMap cells_;
|
||||
CriticalSectionWrapper* cells_lock_;
|
||||
};
|
||||
|
||||
// A LogTable contains multiple rows, where only the latest row is active for
|
||||
// editing. The rows are defined by the ColumnMap, which contains the name of
|
||||
// each column and the length of the column (1 for one-value-columns and greater
|
||||
// than 1 for multi-value-columns).
|
||||
class LogTable {
|
||||
public:
|
||||
LogTable();
|
||||
~LogTable();
|
||||
|
||||
// Adds the column with name column_name to the table. The column will be a
|
||||
// multi-value-column if multi_value_length is greater than 1.
|
||||
// column_name is treated in a case sensitive way.
|
||||
int AddColumn(const std::string& column_name, int multi_value_length);
|
||||
|
||||
// Buffers the current row while it is waiting to be written to file,
|
||||
// which is done by a call to Flush(). A new row is available when the
|
||||
// function returns
|
||||
void NextRow();
|
||||
|
||||
// Inserts a Container into the cell of the column specified with
|
||||
// column_name.
|
||||
// column_name is treated in a case sensitive way.
|
||||
int InsertCell(const std::string& column_name,
|
||||
const Container* value_container);
|
||||
|
||||
// Creates a log file, named as specified in the string file_name, to
|
||||
// where the table will be written when calling Flush().
|
||||
int CreateLogFile(const std::string& file_name);
|
||||
|
||||
// Write all complete rows to file.
|
||||
// May not be called by two threads simultaneously (doing so may result in
|
||||
// a race condition). Will be called by the file_writer_thread_ when that
|
||||
// thread is running.
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
// Collection of multi_value_lengths indexed by column name as std::string
|
||||
typedef std::map<std::string, int> ColumnMap;
|
||||
typedef std::list<Row*> RowList;
|
||||
|
||||
ColumnMap columns_;
|
||||
RowList rows_[2];
|
||||
RowList* rows_history_;
|
||||
RowList* rows_flush_;
|
||||
Row* current_row_;
|
||||
FileWrapper* file_;
|
||||
bool write_header_;
|
||||
CriticalSectionWrapper* table_lock_;
|
||||
};
|
||||
|
||||
Row::Row()
|
||||
: cells_(),
|
||||
cells_lock_(CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
}
|
||||
|
||||
Row::~Row() {
|
||||
for (CellMap::iterator it = cells_.begin(); it != cells_.end();) {
|
||||
delete it->second;
|
||||
// For maps all iterators (except the erased) are valid after an erase
|
||||
cells_.erase(it++);
|
||||
}
|
||||
delete cells_lock_;
|
||||
}
|
||||
|
||||
int Row::InsertCell(const std::string& column_name,
|
||||
const Container* value_container) {
|
||||
CriticalSectionScoped synchronize(cells_lock_);
|
||||
assert(cells_.count(column_name) == 0);
|
||||
if (cells_.count(column_name) > 0)
|
||||
return -1;
|
||||
cells_[column_name] = value_container;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Row::ToString(const std::string& column_name,
|
||||
std::string* value_string) {
|
||||
CriticalSectionScoped synchronize(cells_lock_);
|
||||
const Container* container = cells_[column_name];
|
||||
if (container == NULL) {
|
||||
*value_string = "NaN,";
|
||||
return;
|
||||
}
|
||||
container->ToString(value_string);
|
||||
}
|
||||
|
||||
LogTable::LogTable()
|
||||
: columns_(),
|
||||
rows_(),
|
||||
rows_history_(&rows_[0]),
|
||||
rows_flush_(&rows_[1]),
|
||||
current_row_(new Row),
|
||||
file_(FileWrapper::Create()),
|
||||
write_header_(true),
|
||||
table_lock_(CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
}
|
||||
|
||||
LogTable::~LogTable() {
|
||||
for (RowList::iterator row_it = rows_history_->begin();
|
||||
row_it != rows_history_->end();) {
|
||||
delete *row_it;
|
||||
row_it = rows_history_->erase(row_it);
|
||||
}
|
||||
for (ColumnMap::iterator col_it = columns_.begin();
|
||||
col_it != columns_.end();) {
|
||||
// For maps all iterators (except the erased) are valid after an erase
|
||||
columns_.erase(col_it++);
|
||||
}
|
||||
if (file_ != NULL) {
|
||||
file_->Flush();
|
||||
file_->CloseFile();
|
||||
delete file_;
|
||||
}
|
||||
delete current_row_;
|
||||
delete table_lock_;
|
||||
}
|
||||
|
||||
int LogTable::AddColumn(const std::string& column_name,
|
||||
int multi_value_length) {
|
||||
assert(multi_value_length > 0);
|
||||
if (!write_header_) {
|
||||
// It's not allowed to add new columns after the header
|
||||
// has been written.
|
||||
assert(false);
|
||||
return -1;
|
||||
} else {
|
||||
CriticalSectionScoped synchronize(table_lock_);
|
||||
if (write_header_)
|
||||
columns_[column_name] = multi_value_length;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LogTable::NextRow() {
|
||||
CriticalSectionScoped sync_rows(table_lock_);
|
||||
rows_history_->push_back(current_row_);
|
||||
current_row_ = new Row;
|
||||
}
|
||||
|
||||
int LogTable::InsertCell(const std::string& column_name,
|
||||
const Container* value_container) {
|
||||
CriticalSectionScoped synchronize(table_lock_);
|
||||
assert(columns_.count(column_name) > 0);
|
||||
if (columns_.count(column_name) == 0)
|
||||
return -1;
|
||||
return current_row_->InsertCell(column_name, value_container);
|
||||
}
|
||||
|
||||
int LogTable::CreateLogFile(const std::string& file_name) {
|
||||
if (file_name.length() == 0)
|
||||
return -1;
|
||||
if (file_->Open())
|
||||
return -1;
|
||||
file_->OpenFile(file_name.c_str(),
|
||||
false, // Open with read/write permissions
|
||||
false, // Don't wraparound and write at the beginning when
|
||||
// the file is full
|
||||
true); // Open as a text file
|
||||
if (file_ == NULL)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LogTable::Flush() {
|
||||
ColumnMap::iterator column_it;
|
||||
bool commit_header = false;
|
||||
if (write_header_) {
|
||||
CriticalSectionScoped synchronize(table_lock_);
|
||||
if (write_header_) {
|
||||
commit_header = true;
|
||||
write_header_ = false;
|
||||
}
|
||||
}
|
||||
if (commit_header) {
|
||||
for (column_it = columns_.begin();
|
||||
column_it != columns_.end(); ++column_it) {
|
||||
if (column_it->second > 1) {
|
||||
file_->WriteText("%s[%u],", column_it->first.c_str(),
|
||||
column_it->second);
|
||||
for (int i = 1; i < column_it->second; ++i)
|
||||
file_->WriteText(",");
|
||||
} else {
|
||||
file_->WriteText("%s,", column_it->first.c_str());
|
||||
}
|
||||
}
|
||||
if (columns_.size() > 0)
|
||||
file_->WriteText("\n");
|
||||
}
|
||||
|
||||
// Swap the list used for flushing with the list containing the row history
|
||||
// and clear the history. We also create a local pointer to the new
|
||||
// list used for flushing to avoid race conditions if another thread
|
||||
// calls this function while we are writing.
|
||||
// We don't want to block the list while we're writing to file.
|
||||
{
|
||||
CriticalSectionScoped synchronize(table_lock_);
|
||||
RowList* tmp = rows_flush_;
|
||||
rows_flush_ = rows_history_;
|
||||
rows_history_ = tmp;
|
||||
rows_history_->clear();
|
||||
}
|
||||
|
||||
// Write all complete rows to file and delete them
|
||||
for (RowList::iterator row_it = rows_flush_->begin();
|
||||
row_it != rows_flush_->end();) {
|
||||
for (column_it = columns_.begin();
|
||||
column_it != columns_.end(); ++column_it) {
|
||||
std::string row_string;
|
||||
(*row_it)->ToString(column_it->first, &row_string);
|
||||
file_->WriteText("%s", row_string.c_str());
|
||||
}
|
||||
if (columns_.size() > 0)
|
||||
file_->WriteText("\n");
|
||||
delete *row_it;
|
||||
row_it = rows_flush_->erase(row_it);
|
||||
}
|
||||
}
|
||||
|
||||
int DataLog::CreateLog() {
|
||||
return DataLogImpl::CreateLog();
|
||||
}
|
||||
|
||||
void DataLog::ReturnLog() {
|
||||
return DataLogImpl::ReturnLog();
|
||||
}
|
||||
|
||||
std::string DataLog::Combine(const std::string& table_name, int table_id) {
|
||||
std::stringstream ss;
|
||||
std::string combined_id = table_name;
|
||||
std::string number_suffix;
|
||||
ss << "_" << table_id;
|
||||
ss >> number_suffix;
|
||||
combined_id += number_suffix;
|
||||
std::transform(combined_id.begin(), combined_id.end(), combined_id.begin(),
|
||||
::tolower);
|
||||
return combined_id;
|
||||
}
|
||||
|
||||
int DataLog::AddTable(const std::string& table_name) {
|
||||
DataLogImpl* data_log = DataLogImpl::StaticInstance();
|
||||
if (data_log == NULL)
|
||||
return -1;
|
||||
return data_log->AddTable(table_name);
|
||||
}
|
||||
|
||||
int DataLog::AddColumn(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
int multi_value_length) {
|
||||
DataLogImpl* data_log = DataLogImpl::StaticInstance();
|
||||
if (data_log == NULL)
|
||||
return -1;
|
||||
return data_log->DataLogImpl::StaticInstance()->AddColumn(table_name,
|
||||
column_name,
|
||||
multi_value_length);
|
||||
}
|
||||
|
||||
int DataLog::NextRow(const std::string& table_name) {
|
||||
DataLogImpl* data_log = DataLogImpl::StaticInstance();
|
||||
if (data_log == NULL)
|
||||
return -1;
|
||||
return data_log->DataLogImpl::StaticInstance()->NextRow(table_name);
|
||||
}
|
||||
|
||||
DataLogImpl::DataLogImpl()
|
||||
: counter_(1),
|
||||
tables_(),
|
||||
flush_event_(EventWrapper::Create()),
|
||||
file_writer_thread_(NULL),
|
||||
tables_lock_(RWLockWrapper::CreateRWLock()) {
|
||||
}
|
||||
|
||||
DataLogImpl::~DataLogImpl() {
|
||||
StopThread();
|
||||
Flush(); // Write any remaining rows
|
||||
delete file_writer_thread_;
|
||||
delete flush_event_;
|
||||
for (TableMap::iterator it = tables_.begin(); it != tables_.end();) {
|
||||
delete static_cast<LogTable*>(it->second);
|
||||
// For maps all iterators (except the erased) are valid after an erase
|
||||
tables_.erase(it++);
|
||||
}
|
||||
delete tables_lock_;
|
||||
}
|
||||
|
||||
int DataLogImpl::CreateLog() {
|
||||
CriticalSectionScoped synchronize(crit_sect_.get());
|
||||
if (instance_ == NULL) {
|
||||
instance_ = new DataLogImpl();
|
||||
return instance_->Init();
|
||||
} else {
|
||||
++instance_->counter_;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLogImpl::Init() {
|
||||
file_writer_thread_ = ThreadWrapper::CreateThread(
|
||||
DataLogImpl::Run,
|
||||
instance_,
|
||||
kHighestPriority,
|
||||
"DataLog");
|
||||
if (file_writer_thread_ == NULL)
|
||||
return -1;
|
||||
unsigned int thread_id = 0;
|
||||
bool success = file_writer_thread_->Start(thread_id);
|
||||
if (!success)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataLogImpl* DataLogImpl::StaticInstance() {
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void DataLogImpl::ReturnLog() {
|
||||
CriticalSectionScoped synchronize(crit_sect_.get());
|
||||
if (instance_ && instance_->counter_ > 1) {
|
||||
--instance_->counter_;
|
||||
return;
|
||||
}
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
}
|
||||
|
||||
int DataLogImpl::AddTable(const std::string& table_name) {
|
||||
WriteLockScoped synchronize(*tables_lock_);
|
||||
// Make sure we don't add a table which already exists
|
||||
if (tables_.count(table_name) > 0)
|
||||
return -1;
|
||||
tables_[table_name] = new LogTable();
|
||||
if (tables_[table_name]->CreateLogFile(table_name + ".txt") == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLogImpl::AddColumn(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
int multi_value_length) {
|
||||
ReadLockScoped synchronize(*tables_lock_);
|
||||
if (tables_.count(table_name) == 0)
|
||||
return -1;
|
||||
return tables_[table_name]->AddColumn(column_name, multi_value_length);
|
||||
}
|
||||
|
||||
int DataLogImpl::InsertCell(const std::string& table_name,
|
||||
const std::string& column_name,
|
||||
const Container* value_container) {
|
||||
ReadLockScoped synchronize(*tables_lock_);
|
||||
assert(tables_.count(table_name) > 0);
|
||||
if (tables_.count(table_name) == 0)
|
||||
return -1;
|
||||
return tables_[table_name]->InsertCell(column_name, value_container);
|
||||
}
|
||||
|
||||
int DataLogImpl::NextRow(const std::string& table_name) {
|
||||
ReadLockScoped synchronize(*tables_lock_);
|
||||
if (tables_.count(table_name) == 0)
|
||||
return -1;
|
||||
tables_[table_name]->NextRow();
|
||||
if (file_writer_thread_ == NULL) {
|
||||
// Write every row to file as they get complete.
|
||||
tables_[table_name]->Flush();
|
||||
} else {
|
||||
// Signal a complete row
|
||||
flush_event_->Set();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DataLogImpl::Flush() {
|
||||
ReadLockScoped synchronize(*tables_lock_);
|
||||
for (TableMap::iterator it = tables_.begin(); it != tables_.end(); ++it) {
|
||||
it->second->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
bool DataLogImpl::Run(void* obj) {
|
||||
static_cast<DataLogImpl*>(obj)->Process();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataLogImpl::Process() {
|
||||
// Wait for a row to be complete
|
||||
flush_event_->Wait(WEBRTC_EVENT_INFINITE);
|
||||
Flush();
|
||||
}
|
||||
|
||||
void DataLogImpl::StopThread() {
|
||||
if (file_writer_thread_ != NULL) {
|
||||
file_writer_thread_->SetNotAlive();
|
||||
flush_event_->Set();
|
||||
// Call Stop() repeatedly, waiting for the Flush() call in Process() to
|
||||
// finish.
|
||||
while (!file_writer_thread_->Stop()) continue;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
143
jni/webrtc/system_wrappers/source/data_log_c.cc
Normal file
143
jni/webrtc/system_wrappers/source/data_log_c.cc
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This is the pure C wrapper of the DataLog class.
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log_c.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
extern "C" int WebRtcDataLog_CreateLog() {
|
||||
return webrtc::DataLog::CreateLog();
|
||||
}
|
||||
|
||||
extern "C" void WebRtcDataLog_ReturnLog() {
|
||||
return webrtc::DataLog::ReturnLog();
|
||||
}
|
||||
|
||||
extern "C" char* WebRtcDataLog_Combine(char* combined_name, size_t combined_len,
|
||||
const char* table_name, int table_id) {
|
||||
if (!table_name) return NULL;
|
||||
std::string combined = webrtc::DataLog::Combine(table_name, table_id);
|
||||
if (combined.size() >= combined_len) return NULL;
|
||||
std::copy(combined.begin(), combined.end(), combined_name);
|
||||
combined_name[combined.size()] = '\0';
|
||||
return combined_name;
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_AddTable(const char* table_name) {
|
||||
if (!table_name) return -1;
|
||||
return webrtc::DataLog::AddTable(table_name);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_AddColumn(const char* table_name,
|
||||
const char* column_name,
|
||||
int multi_value_length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::AddColumn(table_name, column_name,
|
||||
multi_value_length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_int(const char* table_name,
|
||||
const char* column_name,
|
||||
int value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_int(const char* table_name,
|
||||
const char* column_name,
|
||||
const int* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_float(const char* table_name,
|
||||
const char* column_name,
|
||||
float value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_float(const char* table_name,
|
||||
const char* column_name,
|
||||
const float* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_double(const char* table_name,
|
||||
const char* column_name,
|
||||
double value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_double(const char* table_name,
|
||||
const char* column_name,
|
||||
const double* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_int32(const char* table_name,
|
||||
const char* column_name,
|
||||
int32_t value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_int32(const char* table_name,
|
||||
const char* column_name,
|
||||
const int32_t* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_uint32(const char* table_name,
|
||||
const char* column_name,
|
||||
uint32_t value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_uint32(const char* table_name,
|
||||
const char* column_name,
|
||||
const uint32_t* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertCell_int64(const char* table_name,
|
||||
const char* column_name,
|
||||
int64_t value) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, value);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_InsertArray_int64(const char* table_name,
|
||||
const char* column_name,
|
||||
const int64_t* values,
|
||||
int length) {
|
||||
if (!table_name || !column_name) return -1;
|
||||
return webrtc::DataLog::InsertCell(table_name, column_name, values, length);
|
||||
}
|
||||
|
||||
extern "C" int WebRtcDataLog_NextRow(const char* table_name) {
|
||||
if (!table_name) return -1;
|
||||
return webrtc::DataLog::NextRow(table_name);
|
||||
}
|
124
jni/webrtc/system_wrappers/source/data_log_c_helpers_unittest.c
Normal file
124
jni/webrtc/system_wrappers/source/data_log_c_helpers_unittest.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/data_log_c_helpers_unittest.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log_c.h"
|
||||
|
||||
enum { kTestArrayLen = 4 };
|
||||
static const char kTableName[] = "c_wrapper_table";
|
||||
static const char kColumnName1[] = "Scalar";
|
||||
static const char kColumnName2[] = "Vector";
|
||||
|
||||
int WebRtcDataLogCHelper_TestCreateLog() {
|
||||
return WebRtcDataLog_CreateLog();
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestReturnLog() {
|
||||
WebRtcDataLog_ReturnLog();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestCombine() {
|
||||
const int kOutLen = strlen(kTableName) + 4; // Room for "_17" + '\0'
|
||||
char* combined_name = malloc(kOutLen * sizeof(char));
|
||||
char* out_ptr = WebRtcDataLog_Combine(combined_name, kOutLen, kTableName, 17);
|
||||
int return_code = 0;
|
||||
if (!out_ptr) {
|
||||
return_code = -1;
|
||||
}
|
||||
if (strcmp(combined_name, "c_wrapper_table_17") != 0) {
|
||||
return_code = -2;
|
||||
}
|
||||
free(combined_name);
|
||||
return return_code;
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestAddTable() {
|
||||
return WebRtcDataLog_AddTable(kTableName);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestAddColumn() {
|
||||
if (WebRtcDataLog_AddColumn(kTableName, kColumnName1, 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (WebRtcDataLog_AddColumn(kTableName, kColumnName2, kTestArrayLen) != 0) {
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestNextRow() {
|
||||
return WebRtcDataLog_NextRow(kTableName);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int() {
|
||||
return WebRtcDataLog_InsertCell_int(kTableName, kColumnName1, 17);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int() {
|
||||
int values[kTestArrayLen] = {1, 2, 3, 4};
|
||||
return WebRtcDataLog_InsertArray_int(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_float() {
|
||||
return WebRtcDataLog_InsertCell_float(kTableName, kColumnName1, 17.0f);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_float() {
|
||||
float values[kTestArrayLen] = {1.0f, 2.0f, 3.0f, 4.0f};
|
||||
return WebRtcDataLog_InsertArray_float(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_double() {
|
||||
return WebRtcDataLog_InsertCell_int(kTableName, kColumnName1, 17.0);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_double() {
|
||||
double values[kTestArrayLen] = {1.0, 2.0, 3.0, 4.0};
|
||||
return WebRtcDataLog_InsertArray_double(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int32() {
|
||||
return WebRtcDataLog_InsertCell_int32(kTableName, kColumnName1, 17);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int32() {
|
||||
int32_t values[kTestArrayLen] = {1, 2, 3, 4};
|
||||
return WebRtcDataLog_InsertArray_int32(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_uint32() {
|
||||
return WebRtcDataLog_InsertCell_uint32(kTableName, kColumnName1, 17);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_uint32() {
|
||||
uint32_t values[kTestArrayLen] = {1, 2, 3, 4};
|
||||
return WebRtcDataLog_InsertArray_uint32(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int64() {
|
||||
return WebRtcDataLog_InsertCell_int64(kTableName, kColumnName1, 17);
|
||||
}
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int64() {
|
||||
int64_t values[kTestArrayLen] = {1, 2, 3, 4};
|
||||
return WebRtcDataLog_InsertArray_int64(kTableName, kColumnName2, values,
|
||||
kTestArrayLen);
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_
|
||||
#define SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int WebRtcDataLogCHelper_TestCreateLog();
|
||||
|
||||
int WebRtcDataLogCHelper_TestReturnLog();
|
||||
|
||||
int WebRtcDataLogCHelper_TestCombine();
|
||||
|
||||
int WebRtcDataLogCHelper_TestAddTable();
|
||||
|
||||
int WebRtcDataLogCHelper_TestAddColumn();
|
||||
|
||||
int WebRtcDataLogCHelper_TestNextRow();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_float();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_float();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_double();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_double();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int32();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int32();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_uint32();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_uint32();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertCell_int64();
|
||||
|
||||
int WebRtcDataLogCHelper_TestInsertArray_int64();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using ::webrtc::DataLog;
|
||||
|
||||
TEST(TestDataLog, IntContainers) {
|
||||
int c = 5;
|
||||
webrtc::ValueContainer<int> v1(c);
|
||||
c = 10;
|
||||
webrtc::ValueContainer<int> v2(c);
|
||||
std::string s1, s2;
|
||||
v1.ToString(&s1);
|
||||
v2.ToString(&s2);
|
||||
ASSERT_EQ(s1, "5,");
|
||||
ASSERT_EQ(s2, "10,");
|
||||
v1 = v2;
|
||||
v1.ToString(&s1);
|
||||
ASSERT_EQ(s1, s2);
|
||||
}
|
||||
|
||||
TEST(TestDataLog, DoubleContainers) {
|
||||
double c = 3.5;
|
||||
webrtc::ValueContainer<double> v1(c);
|
||||
c = 10.3;
|
||||
webrtc::ValueContainer<double> v2(c);
|
||||
std::string s1, s2;
|
||||
v1.ToString(&s1);
|
||||
v2.ToString(&s2);
|
||||
ASSERT_EQ(s1, "3.5,");
|
||||
ASSERT_EQ(s2, "10.3,");
|
||||
v1 = v2;
|
||||
v1.ToString(&s1);
|
||||
ASSERT_EQ(s1, s2);
|
||||
}
|
||||
|
||||
TEST(TestDataLog, MultiValueContainers) {
|
||||
int a[3] = {1, 2, 3};
|
||||
int b[3] = {4, 5, 6};
|
||||
webrtc::MultiValueContainer<int> m1(a, 3);
|
||||
webrtc::MultiValueContainer<int> m2(b, 3);
|
||||
webrtc::MultiValueContainer<int> m3(a, 3);
|
||||
std::string s1, s2, s3;
|
||||
m1.ToString(&s1);
|
||||
m2.ToString(&s2);
|
||||
ASSERT_EQ(s1, "1,2,3,");
|
||||
ASSERT_EQ(s2, "4,5,6,");
|
||||
m1 = m2;
|
||||
m1.ToString(&s1);
|
||||
ASSERT_EQ(s1, s2);
|
||||
m3.ToString(&s3);
|
||||
ASSERT_EQ(s3, "1,2,3,");
|
||||
}
|
88
jni/webrtc/system_wrappers/source/data_log_no_op.cc
Normal file
88
jni/webrtc/system_wrappers/source/data_log_no_op.cc
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int DataLog::CreateLog() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DataLog::ReturnLog() {
|
||||
}
|
||||
|
||||
std::string DataLog::Combine(const std::string& table_name, int table_id) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
int DataLog::AddTable(const std::string& /*table_name*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLog::AddColumn(const std::string& /*table_name*/,
|
||||
const std::string& /*column_name*/,
|
||||
int /*multi_value_length*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLog::NextRow(const std::string& /*table_name*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataLogImpl::DataLogImpl() {
|
||||
}
|
||||
|
||||
DataLogImpl::~DataLogImpl() {
|
||||
}
|
||||
|
||||
DataLogImpl* DataLogImpl::StaticInstance() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DataLogImpl::ReturnLog() {
|
||||
}
|
||||
|
||||
int DataLogImpl::AddTable(const std::string& /*table_name*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLogImpl::AddColumn(const std::string& /*table_name*/,
|
||||
const std::string& /*column_name*/,
|
||||
int /*multi_value_length*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLogImpl::InsertCell(const std::string& /*table_name*/,
|
||||
const std::string& /*column_name*/,
|
||||
const Container* /*value_container*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DataLogImpl::NextRow(const std::string& /*table_name*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DataLogImpl::Flush() {
|
||||
}
|
||||
|
||||
bool DataLogImpl::Run(void* /*obj*/) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataLogImpl::Process() {
|
||||
}
|
||||
|
||||
void DataLogImpl::StopThread() {
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
311
jni/webrtc/system_wrappers/source/data_log_unittest.cc
Normal file
311
jni/webrtc/system_wrappers/source/data_log_unittest.cc
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/data_log_c.h"
|
||||
#include "webrtc/system_wrappers/source/data_log_c_helpers_unittest.h"
|
||||
|
||||
using ::webrtc::DataLog;
|
||||
|
||||
// A class for storing the values expected from a log table column when
|
||||
// verifying a log table file.
|
||||
struct ExpectedValues {
|
||||
public:
|
||||
ExpectedValues()
|
||||
: values(),
|
||||
multi_value_length(1) {
|
||||
}
|
||||
|
||||
ExpectedValues(std::vector<std::string> expected_values,
|
||||
int expected_multi_value_length)
|
||||
: values(expected_values),
|
||||
multi_value_length(expected_multi_value_length) {
|
||||
}
|
||||
|
||||
std::vector<std::string> values;
|
||||
int multi_value_length;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, ExpectedValues> ExpectedValuesMap;
|
||||
|
||||
// A static class used for parsing and verifying data log files.
|
||||
class DataLogParser {
|
||||
public:
|
||||
// Verifies that the log table stored in the file "log_file" corresponds to
|
||||
// the cells and columns specified in "columns".
|
||||
static int VerifyTable(FILE* log_file, const ExpectedValuesMap& columns) {
|
||||
int row = 0;
|
||||
char line_buffer[kMaxLineLength];
|
||||
char* ret = fgets(line_buffer, kMaxLineLength, log_file);
|
||||
EXPECT_FALSE(ret == NULL);
|
||||
if (ret == NULL)
|
||||
return -1;
|
||||
|
||||
std::string line(line_buffer, kMaxLineLength);
|
||||
VerifyHeader(line, columns);
|
||||
while (fgets(line_buffer, kMaxLineLength, log_file) != NULL) {
|
||||
line = std::string(line_buffer, kMaxLineLength);
|
||||
size_t line_position = 0;
|
||||
|
||||
for (ExpectedValuesMap::const_iterator it = columns.begin();
|
||||
it != columns.end(); ++it) {
|
||||
std::string str = ParseElement(line, &line_position,
|
||||
it->second.multi_value_length);
|
||||
EXPECT_EQ(str, it->second.values[row]);
|
||||
if (str != it->second.values[row])
|
||||
return -1;
|
||||
}
|
||||
++row;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verifies the table header stored in "line" to correspond with the header
|
||||
// specified in "columns".
|
||||
static int VerifyHeader(const std::string& line,
|
||||
const ExpectedValuesMap& columns) {
|
||||
size_t line_position = 0;
|
||||
for (ExpectedValuesMap::const_iterator it = columns.begin();
|
||||
it != columns.end(); ++it) {
|
||||
std::string str = ParseElement(line, &line_position,
|
||||
it->second.multi_value_length);
|
||||
EXPECT_EQ(str, it->first);
|
||||
if (str != it->first)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parses out and returns one element from the string "line", which contains
|
||||
// one line read from a log table file. An element can either be a column
|
||||
// header or a cell of a row.
|
||||
static std::string ParseElement(const std::string& line,
|
||||
size_t* line_position,
|
||||
int multi_value_length) {
|
||||
std::string parsed_cell;
|
||||
parsed_cell = "";
|
||||
for (int i = 0; i < multi_value_length; ++i) {
|
||||
size_t next_separator = line.find(',', *line_position);
|
||||
EXPECT_NE(next_separator, std::string::npos);
|
||||
if (next_separator == std::string::npos)
|
||||
break;
|
||||
parsed_cell += line.substr(*line_position,
|
||||
next_separator - *line_position + 1);
|
||||
*line_position = next_separator + 1;
|
||||
}
|
||||
return parsed_cell;
|
||||
}
|
||||
|
||||
// This constant defines the maximum line length the DataLogParser can
|
||||
// parse.
|
||||
enum { kMaxLineLength = 100 };
|
||||
};
|
||||
|
||||
TEST(TestDataLog, CreateReturnTest) {
|
||||
for (int i = 0; i < 10; ++i)
|
||||
ASSERT_EQ(DataLog::CreateLog(), 0);
|
||||
ASSERT_EQ(DataLog::AddTable(DataLog::Combine("a proper table", 1)), 0);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
DataLog::ReturnLog();
|
||||
ASSERT_LT(DataLog::AddTable(DataLog::Combine("table failure", 1)), 0);
|
||||
}
|
||||
|
||||
TEST(TestDataLog, VerifyCombineMethod) {
|
||||
EXPECT_EQ(std::string("a proper table_1"),
|
||||
DataLog::Combine("a proper table", 1));
|
||||
}
|
||||
|
||||
TEST(TestDataLog, VerifySingleTable) {
|
||||
DataLog::CreateLog();
|
||||
DataLog::AddTable(DataLog::Combine("table", 1));
|
||||
DataLog::AddColumn(DataLog::Combine("table", 1), "arrival", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 1), "timestamp", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 1), "size", 5);
|
||||
uint32_t sizes[5] = {1400, 1500, 1600, 1700, 1800};
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
DataLog::InsertCell(DataLog::Combine("table", 1), "arrival",
|
||||
static_cast<double>(i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 1), "timestamp",
|
||||
static_cast<int64_t>(4354 + i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 1), "size", sizes, 5);
|
||||
DataLog::NextRow(DataLog::Combine("table", 1));
|
||||
}
|
||||
DataLog::ReturnLog();
|
||||
// Verify file
|
||||
FILE* table = fopen("table_1.txt", "r");
|
||||
ASSERT_FALSE(table == NULL);
|
||||
// Read the column names and verify with the expected columns.
|
||||
// Note that the columns are written to file in alphabetical order.
|
||||
// Data expected from parsing the file
|
||||
const int kNumberOfRows = 10;
|
||||
std::string string_arrival[kNumberOfRows] = {
|
||||
"0,", "1,", "2,", "3,", "4,",
|
||||
"5,", "6,", "7,", "8,", "9,"
|
||||
};
|
||||
std::string string_timestamp[kNumberOfRows] = {
|
||||
"4354,", "4355,", "4356,", "4357,",
|
||||
"4358,", "4359,", "4360,", "4361,",
|
||||
"4362,", "4363,"
|
||||
};
|
||||
std::string string_sizes = "1400,1500,1600,1700,1800,";
|
||||
ExpectedValuesMap expected;
|
||||
expected["arrival,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_arrival,
|
||||
string_arrival +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
expected["size[5],,,,,"] = ExpectedValues(
|
||||
std::vector<std::string>(10, string_sizes), 5);
|
||||
expected["timestamp,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_timestamp,
|
||||
string_timestamp +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
|
||||
fclose(table);
|
||||
}
|
||||
|
||||
TEST(TestDataLog, VerifyMultipleTables) {
|
||||
DataLog::CreateLog();
|
||||
DataLog::AddTable(DataLog::Combine("table", 2));
|
||||
DataLog::AddTable(DataLog::Combine("table", 3));
|
||||
DataLog::AddColumn(DataLog::Combine("table", 2), "arrival", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 2), "timestamp", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 2), "size", 1);
|
||||
DataLog::AddTable(DataLog::Combine("table", 4));
|
||||
DataLog::AddColumn(DataLog::Combine("table", 3), "timestamp", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 3), "arrival", 1);
|
||||
DataLog::AddColumn(DataLog::Combine("table", 4), "size", 1);
|
||||
for (int32_t i = 0; i < 10; ++i) {
|
||||
DataLog::InsertCell(DataLog::Combine("table", 2), "arrival",
|
||||
static_cast<int32_t>(i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 2), "timestamp",
|
||||
static_cast<int32_t>(4354 + i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 2), "size",
|
||||
static_cast<int32_t>(1200 + 10 * i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 3), "timestamp",
|
||||
static_cast<int32_t>(4354 + i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 3), "arrival",
|
||||
static_cast<int32_t>(i));
|
||||
DataLog::InsertCell(DataLog::Combine("table", 4), "size",
|
||||
static_cast<int32_t>(1200 + 10 * i));
|
||||
DataLog::NextRow(DataLog::Combine("table", 4));
|
||||
DataLog::NextRow(DataLog::Combine("table", 2));
|
||||
DataLog::NextRow(DataLog::Combine("table", 3));
|
||||
}
|
||||
DataLog::ReturnLog();
|
||||
|
||||
// Data expected from parsing the file
|
||||
const int kNumberOfRows = 10;
|
||||
std::string string_arrival[kNumberOfRows] = {
|
||||
"0,", "1,", "2,", "3,", "4,",
|
||||
"5,", "6,", "7,", "8,", "9,"
|
||||
};
|
||||
std::string string_timestamp[kNumberOfRows] = {
|
||||
"4354,", "4355,", "4356,", "4357,",
|
||||
"4358,", "4359,", "4360,", "4361,",
|
||||
"4362,", "4363,"
|
||||
};
|
||||
std::string string_size[kNumberOfRows] = {
|
||||
"1200,", "1210,", "1220,", "1230,",
|
||||
"1240,", "1250,", "1260,", "1270,",
|
||||
"1280,", "1290,"
|
||||
};
|
||||
|
||||
// Verify table 2
|
||||
{
|
||||
FILE* table = fopen("table_2.txt", "r");
|
||||
ASSERT_FALSE(table == NULL);
|
||||
ExpectedValuesMap expected;
|
||||
expected["arrival,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_arrival,
|
||||
string_arrival +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
expected["size,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_size,
|
||||
string_size + kNumberOfRows),
|
||||
1);
|
||||
expected["timestamp,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_timestamp,
|
||||
string_timestamp +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
|
||||
fclose(table);
|
||||
}
|
||||
|
||||
// Verify table 3
|
||||
{
|
||||
FILE* table = fopen("table_3.txt", "r");
|
||||
ASSERT_FALSE(table == NULL);
|
||||
ExpectedValuesMap expected;
|
||||
expected["arrival,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_arrival,
|
||||
string_arrival +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
expected["timestamp,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_timestamp,
|
||||
string_timestamp +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
|
||||
fclose(table);
|
||||
}
|
||||
|
||||
// Verify table 4
|
||||
{
|
||||
FILE* table = fopen("table_4.txt", "r");
|
||||
ASSERT_FALSE(table == NULL);
|
||||
ExpectedValuesMap expected;
|
||||
expected["size,"] = ExpectedValues(
|
||||
std::vector<std::string>(string_size,
|
||||
string_size +
|
||||
kNumberOfRows),
|
||||
1);
|
||||
ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
|
||||
fclose(table);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestDataLogCWrapper, VerifyCWrapper) {
|
||||
// Simply call all C wrapper log functions through the C helper unittests.
|
||||
// Main purpose is to make sure that the linkage is correct.
|
||||
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestCreateLog());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestCombine());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddTable());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddColumn());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_float());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_float());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_double());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_double());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int32());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int32());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_uint32());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_uint32());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int64());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int64());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
|
||||
EXPECT_EQ(0, WebRtcDataLogCHelper_TestReturnLog());
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/data_log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using ::webrtc::DataLog;
|
||||
|
||||
const char* kDataLogFileName = "table_1.txt";
|
||||
|
||||
void PerformLogging(const std::string& table_name) {
|
||||
// Simulate normal DataTable logging behavior using this table name.
|
||||
ASSERT_EQ(0, DataLog::AddTable(table_name));
|
||||
ASSERT_EQ(0, DataLog::AddColumn(table_name, "test", 1));
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// TODO(kjellander): Check InsertCell result when the DataLog dummy is
|
||||
// fixed.
|
||||
DataLog::InsertCell(table_name, "test", static_cast<double>(i));
|
||||
ASSERT_EQ(0, DataLog::NextRow(table_name));
|
||||
}
|
||||
}
|
||||
|
||||
// Simple test to verify DataLog is still working when the GYP variable
|
||||
// enable_data_logging==0 (the default case).
|
||||
TEST(TestDataLogDisabled, VerifyLoggingWorks) {
|
||||
ASSERT_EQ(0, DataLog::CreateLog());
|
||||
// Generate a table_name name and assure it's an empty string
|
||||
// (dummy behavior).
|
||||
std::string table_name = DataLog::Combine("table", 1);
|
||||
ASSERT_EQ("", table_name);
|
||||
PerformLogging(table_name);
|
||||
DataLog::ReturnLog();
|
||||
}
|
||||
|
||||
TEST(TestDataLogDisabled, EnsureNoFileIsWritten) {
|
||||
// Remove any previous data files on disk:
|
||||
remove(kDataLogFileName);
|
||||
ASSERT_EQ(0, DataLog::CreateLog());
|
||||
// Don't use the table name we would get from Combine on a disabled DataLog.
|
||||
// Use "table_1" instead (which is what an enabled DataLog would give us).
|
||||
PerformLogging("table_1");
|
||||
DataLog::ReturnLog();
|
||||
// Verify no data log file have been written:
|
||||
ASSERT_EQ(NULL, fopen(kDataLogFileName, "r"));
|
||||
}
|
33
jni/webrtc/system_wrappers/source/event.cc
Normal file
33
jni/webrtc/system_wrappers/source/event.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/event_win.h"
|
||||
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_posix.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
EventWrapper* EventWrapper::Create() {
|
||||
#if defined(_WIN32)
|
||||
return new EventWindows();
|
||||
#else
|
||||
return EventPosix::Create();
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
294
jni/webrtc/system_wrappers/source/event_posix.cc
Normal file
294
jni/webrtc/system_wrappers/source/event_posix.cc
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/event_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const long int E6 = 1000000;
|
||||
const long int E9 = 1000 * E6;
|
||||
|
||||
EventWrapper* EventPosix::Create() {
|
||||
EventPosix* ptr = new EventPosix;
|
||||
if (!ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int error = ptr->Construct();
|
||||
if (error) {
|
||||
delete ptr;
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
EventPosix::EventPosix()
|
||||
: timer_thread_(0),
|
||||
timer_event_(0),
|
||||
periodic_(false),
|
||||
time_(0),
|
||||
count_(0),
|
||||
state_(kDown) {
|
||||
}
|
||||
|
||||
int EventPosix::Construct() {
|
||||
// Set start time to zero
|
||||
memset(&created_at_, 0, sizeof(created_at_));
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
int result = pthread_mutex_init(&mutex_, &attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
result = pthread_cond_init(&cond_, 0);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
pthread_condattr_t cond_attr;
|
||||
result = pthread_condattr_init(&cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_cond_init(&cond_, &cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_destroy(&cond_attr);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
EventPosix::~EventPosix() {
|
||||
StopTimer();
|
||||
pthread_cond_destroy(&cond_);
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
bool EventPosix::Reset() {
|
||||
if (0 != pthread_mutex_lock(&mutex_)) {
|
||||
return false;
|
||||
}
|
||||
state_ = kDown;
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventPosix::Set() {
|
||||
if (0 != pthread_mutex_lock(&mutex_)) {
|
||||
return false;
|
||||
}
|
||||
state_ = kUp;
|
||||
// Release all waiting threads
|
||||
pthread_cond_broadcast(&cond_);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventPosix::Wait(unsigned long timeout) {
|
||||
int ret_val = 0;
|
||||
if (0 != pthread_mutex_lock(&mutex_)) {
|
||||
return kEventError;
|
||||
}
|
||||
|
||||
if (kDown == state_) {
|
||||
if (WEBRTC_EVENT_INFINITE != timeout) {
|
||||
timespec end_at;
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &end_at);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_at);
|
||||
#endif
|
||||
#else
|
||||
timeval value;
|
||||
struct timezone time_zone;
|
||||
time_zone.tz_minuteswest = 0;
|
||||
time_zone.tz_dsttime = 0;
|
||||
gettimeofday(&value, &time_zone);
|
||||
TIMEVAL_TO_TIMESPEC(&value, &end_at);
|
||||
#endif
|
||||
end_at.tv_sec += timeout / 1000;
|
||||
end_at.tv_nsec += (timeout - (timeout / 1000) * 1000) * E6;
|
||||
|
||||
if (end_at.tv_nsec >= E9) {
|
||||
end_at.tv_sec++;
|
||||
end_at.tv_nsec -= E9;
|
||||
}
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
|
||||
} else {
|
||||
ret_val = pthread_cond_wait(&cond_, &mutex_);
|
||||
}
|
||||
}
|
||||
|
||||
state_ = kDown;
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
switch (ret_val) {
|
||||
case 0:
|
||||
return kEventSignaled;
|
||||
case ETIMEDOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
EventTypeWrapper EventPosix::Wait(timespec& wake_at) {
|
||||
int ret_val = 0;
|
||||
if (0 != pthread_mutex_lock(&mutex_)) {
|
||||
return kEventError;
|
||||
}
|
||||
|
||||
if (kUp != state_) {
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, &wake_at);
|
||||
}
|
||||
state_ = kDown;
|
||||
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
switch (ret_val) {
|
||||
case 0:
|
||||
return kEventSignaled;
|
||||
case ETIMEDOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventPosix::StartTimer(bool periodic, unsigned long time) {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (timer_thread_) {
|
||||
if (periodic_) {
|
||||
// Timer already started.
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return false;
|
||||
} else {
|
||||
// New one shot timer
|
||||
time_ = time;
|
||||
created_at_.tv_sec = 0;
|
||||
timer_event_->Set();
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the timer thread
|
||||
timer_event_ = static_cast<EventPosix*>(EventWrapper::Create());
|
||||
const char* thread_name = "WebRtc_event_timer_thread";
|
||||
timer_thread_ = ThreadWrapper::CreateThread(Run, this, kRealtimePriority,
|
||||
thread_name);
|
||||
periodic_ = periodic;
|
||||
time_ = time;
|
||||
unsigned int id = 0;
|
||||
bool started = timer_thread_->Start(id);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
||||
bool EventPosix::Run(ThreadObj obj) {
|
||||
return static_cast<EventPosix*>(obj)->Process();
|
||||
}
|
||||
|
||||
bool EventPosix::Process() {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (created_at_.tv_sec == 0) {
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &created_at_);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &created_at_);
|
||||
#endif
|
||||
#else
|
||||
timeval value;
|
||||
struct timezone time_zone;
|
||||
time_zone.tz_minuteswest = 0;
|
||||
time_zone.tz_dsttime = 0;
|
||||
gettimeofday(&value, &time_zone);
|
||||
TIMEVAL_TO_TIMESPEC(&value, &created_at_);
|
||||
#endif
|
||||
count_ = 0;
|
||||
}
|
||||
|
||||
timespec end_at;
|
||||
unsigned long long time = time_ * ++count_;
|
||||
end_at.tv_sec = created_at_.tv_sec + time / 1000;
|
||||
end_at.tv_nsec = created_at_.tv_nsec + (time - (time / 1000) * 1000) * E6;
|
||||
|
||||
if (end_at.tv_nsec >= E9) {
|
||||
end_at.tv_sec++;
|
||||
end_at.tv_nsec -= E9;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
switch (timer_event_->Wait(end_at)) {
|
||||
case kEventSignaled:
|
||||
return true;
|
||||
case kEventError:
|
||||
return false;
|
||||
case kEventTimeout:
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (periodic_ || count_ == 1)
|
||||
Set();
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventPosix::StopTimer() {
|
||||
if (timer_thread_) {
|
||||
timer_thread_->SetNotAlive();
|
||||
}
|
||||
if (timer_event_) {
|
||||
timer_event_->Set();
|
||||
}
|
||||
if (timer_thread_) {
|
||||
if (!timer_thread_->Stop()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete timer_thread_;
|
||||
timer_thread_ = 0;
|
||||
}
|
||||
if (timer_event_) {
|
||||
delete timer_event_;
|
||||
timer_event_ = 0;
|
||||
}
|
||||
|
||||
// Set time to zero to force new reference time for the timer.
|
||||
memset(&created_at_, 0, sizeof(created_at_));
|
||||
count_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
65
jni/webrtc/system_wrappers/source/event_posix.h
Normal file
65
jni/webrtc/system_wrappers/source/event_posix.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum State {
|
||||
kUp = 1,
|
||||
kDown = 2
|
||||
};
|
||||
|
||||
class EventPosix : public EventWrapper {
|
||||
public:
|
||||
static EventWrapper* Create();
|
||||
|
||||
virtual ~EventPosix();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time) OVERRIDE;
|
||||
virtual bool Set() OVERRIDE;
|
||||
virtual bool Reset() OVERRIDE;
|
||||
|
||||
virtual bool StartTimer(bool periodic, unsigned long time) OVERRIDE;
|
||||
virtual bool StopTimer() OVERRIDE;
|
||||
|
||||
private:
|
||||
EventPosix();
|
||||
int Construct();
|
||||
|
||||
static bool Run(ThreadObj obj);
|
||||
bool Process();
|
||||
EventTypeWrapper Wait(timespec& wake_at);
|
||||
|
||||
private:
|
||||
pthread_cond_t cond_;
|
||||
pthread_mutex_t mutex_;
|
||||
|
||||
ThreadWrapper* timer_thread_;
|
||||
EventPosix* timer_event_;
|
||||
timespec created_at_;
|
||||
|
||||
bool periodic_;
|
||||
unsigned long time_; // In ms
|
||||
unsigned long count_;
|
||||
State state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
60
jni/webrtc/system_wrappers/source/event_tracer.cc
Normal file
60
jni/webrtc/system_wrappers/source/event_tracer.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_tracer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
GetCategoryEnabledPtr g_get_category_enabled_ptr = 0;
|
||||
AddTraceEventPtr g_add_trace_event_ptr = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetupEventTracer(GetCategoryEnabledPtr get_category_enabled_ptr,
|
||||
AddTraceEventPtr add_trace_event_ptr) {
|
||||
g_get_category_enabled_ptr = get_category_enabled_ptr;
|
||||
g_add_trace_event_ptr = add_trace_event_ptr;
|
||||
}
|
||||
|
||||
// static
|
||||
const unsigned char* EventTracer::GetCategoryEnabled(const char* name) {
|
||||
if (g_get_category_enabled_ptr)
|
||||
return g_get_category_enabled_ptr(name);
|
||||
|
||||
// A string with null terminator means category is disabled.
|
||||
return reinterpret_cast<const unsigned char*>("\0");
|
||||
}
|
||||
|
||||
// static
|
||||
void EventTracer::AddTraceEvent(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
int num_args,
|
||||
const char** arg_names,
|
||||
const unsigned char* arg_types,
|
||||
const unsigned long long* arg_values,
|
||||
unsigned char flags) {
|
||||
if (g_add_trace_event_ptr) {
|
||||
g_add_trace_event_ptr(phase,
|
||||
category_enabled,
|
||||
name,
|
||||
id,
|
||||
num_args,
|
||||
arg_names,
|
||||
arg_types,
|
||||
arg_values,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
82
jni/webrtc/system_wrappers/source/event_tracer_unittest.cc
Normal file
82
jni/webrtc/system_wrappers/source/event_tracer_unittest.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_tracer.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/static_instance.h"
|
||||
#include "webrtc/system_wrappers/interface/trace_event.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class TestStatistics {
|
||||
public:
|
||||
TestStatistics() : events_logged_(0) {
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
events_logged_ = 0;
|
||||
}
|
||||
|
||||
void Increment() {
|
||||
++events_logged_;
|
||||
}
|
||||
|
||||
int Count() const { return events_logged_; }
|
||||
|
||||
static TestStatistics* Get() {
|
||||
static TestStatistics* test_stats = NULL;
|
||||
if (!test_stats)
|
||||
test_stats = new TestStatistics();
|
||||
return test_stats;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_logged_;
|
||||
};
|
||||
|
||||
static const unsigned char* GetCategoryEnabledHandler(const char* name) {
|
||||
return reinterpret_cast<const unsigned char*>("test");
|
||||
}
|
||||
|
||||
static void AddTraceEventHandler(char phase,
|
||||
const unsigned char* category_enabled,
|
||||
const char* name,
|
||||
unsigned long long id,
|
||||
int num_args,
|
||||
const char** arg_names,
|
||||
const unsigned char* arg_types,
|
||||
const unsigned long long* arg_values,
|
||||
unsigned char flags) {
|
||||
TestStatistics::Get()->Increment();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(EventTracerTest, EventTracerDisabled) {
|
||||
{
|
||||
TRACE_EVENT0("test", "EventTracerDisabled");
|
||||
}
|
||||
EXPECT_FALSE(TestStatistics::Get()->Count());
|
||||
TestStatistics::Get()->Reset();
|
||||
}
|
||||
|
||||
TEST(EventTracerTest, ScopedTraceEvent) {
|
||||
SetupEventTracer(&GetCategoryEnabledHandler, &AddTraceEventHandler);
|
||||
{
|
||||
TRACE_EVENT0("test", "ScopedTraceEvent");
|
||||
}
|
||||
EXPECT_EQ(2, TestStatistics::Get()->Count());
|
||||
TestStatistics::Get()->Reset();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
77
jni/webrtc/system_wrappers/source/event_win.cc
Normal file
77
jni/webrtc/system_wrappers/source/event_win.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/event_win.h"
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
EventWindows::EventWindows()
|
||||
: event_(::CreateEvent(NULL, // security attributes
|
||||
FALSE, // manual reset
|
||||
FALSE, // initial state
|
||||
NULL)), // name of event
|
||||
timerID_(NULL) {
|
||||
}
|
||||
|
||||
EventWindows::~EventWindows() {
|
||||
StopTimer();
|
||||
CloseHandle(event_);
|
||||
}
|
||||
|
||||
bool EventWindows::Set() {
|
||||
// Note: setting an event that is already set has no effect.
|
||||
return SetEvent(event_) == 1;
|
||||
}
|
||||
|
||||
bool EventWindows::Reset() {
|
||||
return ResetEvent(event_) == 1;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventWindows::Wait(unsigned long max_time) {
|
||||
unsigned long res = WaitForSingleObject(event_, max_time);
|
||||
switch (res) {
|
||||
case WAIT_OBJECT_0:
|
||||
return kEventSignaled;
|
||||
case WAIT_TIMEOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventWindows::StartTimer(bool periodic, unsigned long time) {
|
||||
if (timerID_ != NULL) {
|
||||
timeKillEvent(timerID_);
|
||||
timerID_ = NULL;
|
||||
}
|
||||
|
||||
if (periodic) {
|
||||
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
|
||||
TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE);
|
||||
} else {
|
||||
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
|
||||
TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
|
||||
}
|
||||
|
||||
return timerID_ != NULL;
|
||||
}
|
||||
|
||||
bool EventWindows::StopTimer() {
|
||||
if (timerID_ != NULL) {
|
||||
timeKillEvent(timerID_);
|
||||
timerID_ = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
jni/webrtc/system_wrappers/source/event_win.h
Normal file
41
jni/webrtc/system_wrappers/source/event_win.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventWindows : public EventWrapper {
|
||||
public:
|
||||
EventWindows();
|
||||
virtual ~EventWindows();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time);
|
||||
virtual bool Set();
|
||||
virtual bool Reset();
|
||||
|
||||
virtual bool StartTimer(bool periodic, unsigned long time);
|
||||
virtual bool StopTimer();
|
||||
|
||||
private:
|
||||
HANDLE event_;
|
||||
uint32_t timerID_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
22
jni/webrtc/system_wrappers/source/field_trial_default.cc
Normal file
22
jni/webrtc/system_wrappers/source/field_trial_default.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "webrtc/system_wrappers/interface/field_trial.h"
|
||||
|
||||
// Clients of webrtc that do not want to configure field trials can link with
|
||||
// this instead of providing their own implementation.
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
std::string FindFullName(const std::string& name) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
278
jni/webrtc/system_wrappers/source/file_impl.cc
Normal file
278
jni/webrtc/system_wrappers/source/file_impl.cc
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/file_impl.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FileWrapper* FileWrapper::Create() {
|
||||
return new FileWrapperImpl();
|
||||
}
|
||||
|
||||
FileWrapperImpl::FileWrapperImpl()
|
||||
: rw_lock_(RWLockWrapper::CreateRWLock()),
|
||||
id_(NULL),
|
||||
managed_file_handle_(true),
|
||||
open_(false),
|
||||
looping_(false),
|
||||
read_only_(false),
|
||||
max_size_in_bytes_(0),
|
||||
size_in_bytes_(0) {
|
||||
memset(file_name_utf8_, 0, kMaxFileNameSize);
|
||||
}
|
||||
|
||||
FileWrapperImpl::~FileWrapperImpl() {
|
||||
if (id_ != NULL && managed_file_handle_) {
|
||||
fclose(id_);
|
||||
}
|
||||
}
|
||||
|
||||
int FileWrapperImpl::CloseFile() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
return CloseFileImpl();
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Rewind() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (looping_ || !read_only_) {
|
||||
if (id_ != NULL) {
|
||||
size_in_bytes_ = 0;
|
||||
return fseek(id_, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::SetMaxFileSize(size_t bytes) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
max_size_in_bytes_ = bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Flush() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const {
|
||||
ReadLockScoped read(*rw_lock_);
|
||||
size_t length = strlen(file_name_utf8_);
|
||||
if (length > kMaxFileNameSize) {
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
if (length < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make sure to NULL terminate
|
||||
if (size < length) {
|
||||
length = size - 1;
|
||||
}
|
||||
memcpy(file_name_utf8, file_name_utf8_, length);
|
||||
file_name_utf8[length] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FileWrapperImpl::Open() const {
|
||||
ReadLockScoped read(*rw_lock_);
|
||||
return open_;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only,
|
||||
bool loop, bool text) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (id_ != NULL && !managed_file_handle_)
|
||||
return -1;
|
||||
size_t length = strlen(file_name_utf8);
|
||||
if (length > kMaxFileNameSize - 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_only_ = read_only;
|
||||
|
||||
FILE* tmp_id = NULL;
|
||||
#if defined _WIN32
|
||||
wchar_t wide_file_name[kMaxFileNameSize];
|
||||
wide_file_name[0] = 0;
|
||||
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0, // UTF8 flag
|
||||
file_name_utf8,
|
||||
-1, // Null terminated string
|
||||
wide_file_name,
|
||||
kMaxFileNameSize);
|
||||
if (text) {
|
||||
if (read_only) {
|
||||
tmp_id = _wfopen(wide_file_name, L"rt");
|
||||
} else {
|
||||
tmp_id = _wfopen(wide_file_name, L"wt");
|
||||
}
|
||||
} else {
|
||||
if (read_only) {
|
||||
tmp_id = _wfopen(wide_file_name, L"rb");
|
||||
} else {
|
||||
tmp_id = _wfopen(wide_file_name, L"wb");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (text) {
|
||||
if (read_only) {
|
||||
tmp_id = fopen(file_name_utf8, "rt");
|
||||
} else {
|
||||
tmp_id = fopen(file_name_utf8, "wt");
|
||||
}
|
||||
} else {
|
||||
if (read_only) {
|
||||
tmp_id = fopen(file_name_utf8, "rb");
|
||||
} else {
|
||||
tmp_id = fopen(file_name_utf8, "wb");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmp_id != NULL) {
|
||||
// +1 comes from copying the NULL termination character.
|
||||
memcpy(file_name_utf8_, file_name_utf8, length + 1);
|
||||
if (id_ != NULL) {
|
||||
fclose(id_);
|
||||
}
|
||||
id_ = tmp_id;
|
||||
managed_file_handle_ = true;
|
||||
looping_ = loop;
|
||||
open_ = true;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
if (id_ != NULL) {
|
||||
if (managed_file_handle_)
|
||||
fclose(id_);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
id_ = handle;
|
||||
managed_file_handle_ = manage_file;
|
||||
read_only_ = read_only;
|
||||
looping_ = loop;
|
||||
open_ = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Read(void* buf, int length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
if (id_ == NULL)
|
||||
return -1;
|
||||
|
||||
int bytes_read = static_cast<int>(fread(buf, 1, length, id_));
|
||||
if (bytes_read != length && !looping_) {
|
||||
CloseFileImpl();
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::WriteText(const char* format, ...) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (format == NULL)
|
||||
return -1;
|
||||
|
||||
if (read_only_)
|
||||
return -1;
|
||||
|
||||
if (id_ == NULL)
|
||||
return -1;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int num_chars = vfprintf(id_, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (num_chars >= 0) {
|
||||
return num_chars;
|
||||
} else {
|
||||
CloseFileImpl();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileWrapperImpl::Write(const void* buf, int length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (buf == NULL)
|
||||
return false;
|
||||
|
||||
if (length < 0)
|
||||
return false;
|
||||
|
||||
if (read_only_)
|
||||
return false;
|
||||
|
||||
if (id_ == NULL)
|
||||
return false;
|
||||
|
||||
// Check if it's time to stop writing.
|
||||
if (max_size_in_bytes_ > 0 &&
|
||||
(size_in_bytes_ + length) > max_size_in_bytes_) {
|
||||
FlushImpl();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_bytes = fwrite(buf, 1, length, id_);
|
||||
if (num_bytes > 0) {
|
||||
size_in_bytes_ += num_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
CloseFileImpl();
|
||||
return false;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::CloseFileImpl() {
|
||||
if (id_ != NULL) {
|
||||
if (managed_file_handle_)
|
||||
fclose(id_);
|
||||
id_ = NULL;
|
||||
}
|
||||
memset(file_name_utf8_, 0, kMaxFileNameSize);
|
||||
open_ = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::FlushImpl() {
|
||||
if (id_ != NULL) {
|
||||
return fflush(id_);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
70
jni/webrtc/system_wrappers/source/file_impl.h
Normal file
70
jni/webrtc/system_wrappers/source/file_impl.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/file_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWrapper;
|
||||
|
||||
class FileWrapperImpl : public FileWrapper {
|
||||
public:
|
||||
FileWrapperImpl();
|
||||
virtual ~FileWrapperImpl();
|
||||
|
||||
virtual int FileName(char* file_name_utf8,
|
||||
size_t size) const OVERRIDE;
|
||||
|
||||
virtual bool Open() const OVERRIDE;
|
||||
|
||||
virtual int OpenFile(const char* file_name_utf8,
|
||||
bool read_only,
|
||||
bool loop = false,
|
||||
bool text = false) OVERRIDE;
|
||||
|
||||
virtual int OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop = false) OVERRIDE;
|
||||
|
||||
virtual int CloseFile() OVERRIDE;
|
||||
virtual int SetMaxFileSize(size_t bytes) OVERRIDE;
|
||||
virtual int Flush() OVERRIDE;
|
||||
|
||||
virtual int Read(void* buf, int length) OVERRIDE;
|
||||
virtual bool Write(const void* buf, int length) OVERRIDE;
|
||||
virtual int WriteText(const char* format, ...) OVERRIDE;
|
||||
virtual int Rewind() OVERRIDE;
|
||||
|
||||
private:
|
||||
int CloseFileImpl();
|
||||
int FlushImpl();
|
||||
|
||||
scoped_ptr<RWLockWrapper> rw_lock_;
|
||||
|
||||
FILE* id_;
|
||||
bool managed_file_handle_;
|
||||
bool open_;
|
||||
bool looping_;
|
||||
bool read_only_;
|
||||
size_t max_size_in_bytes_; // -1 indicates file size limitation is off
|
||||
size_t size_in_bytes_;
|
||||
char file_name_utf8_[kMaxFileNameSize];
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
63
jni/webrtc/system_wrappers/source/logcat_trace_context.cc
Normal file
63
jni/webrtc/system_wrappers/source/logcat_trace_context.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
|
||||
|
||||
#include <android/log.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static android_LogPriority AndroidLogPriorityFromWebRtcLogLevel(
|
||||
TraceLevel webrtc_level) {
|
||||
// NOTE: this mapping is somewhat arbitrary. StateInfo and Info are mapped
|
||||
// to DEBUG because they are highly verbose in webrtc code (which is
|
||||
// unfortunate).
|
||||
switch (webrtc_level) {
|
||||
case webrtc::kTraceStateInfo: return ANDROID_LOG_DEBUG;
|
||||
case webrtc::kTraceWarning: return ANDROID_LOG_WARN;
|
||||
case webrtc::kTraceError: return ANDROID_LOG_ERROR;
|
||||
case webrtc::kTraceCritical: return ANDROID_LOG_FATAL;
|
||||
case webrtc::kTraceApiCall: return ANDROID_LOG_VERBOSE;
|
||||
case webrtc::kTraceModuleCall: return ANDROID_LOG_VERBOSE;
|
||||
case webrtc::kTraceMemory: return ANDROID_LOG_VERBOSE;
|
||||
case webrtc::kTraceTimer: return ANDROID_LOG_VERBOSE;
|
||||
case webrtc::kTraceStream: return ANDROID_LOG_VERBOSE;
|
||||
case webrtc::kTraceDebug: return ANDROID_LOG_DEBUG;
|
||||
case webrtc::kTraceInfo: return ANDROID_LOG_DEBUG;
|
||||
case webrtc::kTraceTerseInfo: return ANDROID_LOG_INFO;
|
||||
default:
|
||||
LOG(LS_ERROR) << "Unexpected log level" << webrtc_level;
|
||||
return ANDROID_LOG_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
LogcatTraceContext::LogcatTraceContext() {
|
||||
webrtc::Trace::CreateTrace();
|
||||
if (webrtc::Trace::SetTraceCallback(this) != 0)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
LogcatTraceContext::~LogcatTraceContext() {
|
||||
if (webrtc::Trace::SetTraceCallback(NULL) != 0)
|
||||
assert(false);
|
||||
webrtc::Trace::ReturnTrace();
|
||||
}
|
||||
|
||||
void LogcatTraceContext::Print(TraceLevel level,
|
||||
const char* message,
|
||||
int length) {
|
||||
__android_log_print(AndroidLogPriorityFromWebRtcLogLevel(level),
|
||||
"WEBRTC", "%.*s", length, message);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
61
jni/webrtc/system_wrappers/source/logging.cc
Normal file
61
jni/webrtc/system_wrappers/source/logging.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
TraceLevel WebRtcSeverity(LoggingSeverity sev) {
|
||||
switch (sev) {
|
||||
// TODO(ajm): SENSITIVE doesn't have a corresponding webrtc level.
|
||||
case LS_SENSITIVE: return kTraceInfo;
|
||||
case LS_VERBOSE: return kTraceInfo;
|
||||
case LS_INFO: return kTraceTerseInfo;
|
||||
case LS_WARNING: return kTraceWarning;
|
||||
case LS_ERROR: return kTraceError;
|
||||
default: return kTraceNone;
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeFile(const char* file) {
|
||||
const char* end1 = ::strrchr(file, '/');
|
||||
const char* end2 = ::strrchr(file, '\\');
|
||||
if (!end1 && !end2)
|
||||
return file;
|
||||
else
|
||||
return (end1 > end2) ? end1 + 1 : end2 + 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev)
|
||||
: severity_(sev) {
|
||||
print_stream_ << "(" << DescribeFile(file) << ":" << line << "): ";
|
||||
}
|
||||
|
||||
bool LogMessage::Loggable(LoggingSeverity sev) {
|
||||
// |level_filter| is a bitmask, unlike libjingle's minimum severity value.
|
||||
return WebRtcSeverity(sev) & Trace::level_filter() ? true : false;
|
||||
}
|
||||
|
||||
LogMessage::~LogMessage() {
|
||||
const std::string& str = print_stream_.str();
|
||||
Trace::Add(WebRtcSeverity(severity_), kTraceUndefined, 0, str.c_str());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
89
jni/webrtc/system_wrappers/source/logging_unittest.cc
Normal file
89
jni/webrtc/system_wrappers/source/logging_unittest.cc
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/logging.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/interface/sleep.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
class LoggingTest : public ::testing::Test, public TraceCallback {
|
||||
public:
|
||||
virtual void Print(TraceLevel level, const char* msg, int length) {
|
||||
CriticalSectionScoped cs(crit_.get());
|
||||
// We test the length here to ensure (with high likelihood) that only our
|
||||
// traces will be tested.
|
||||
if (level_ != kTraceNone && static_cast<int>(expected_log_.str().size()) ==
|
||||
length - Trace::kBoilerplateLength - 1) {
|
||||
EXPECT_EQ(level_, level);
|
||||
EXPECT_EQ(expected_log_.str(), &msg[Trace::kBoilerplateLength]);
|
||||
level_ = kTraceNone;
|
||||
cv_->Wake();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
LoggingTest()
|
||||
: crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
cv_(ConditionVariableWrapper::CreateConditionVariable()),
|
||||
level_(kTraceNone),
|
||||
expected_log_() {
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
Trace::CreateTrace();
|
||||
Trace::SetTraceCallback(this);
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
Trace::SetTraceCallback(NULL);
|
||||
Trace::ReturnTrace();
|
||||
CriticalSectionScoped cs(crit_.get());
|
||||
ASSERT_EQ(kTraceNone, level_) << "Print() was not called";
|
||||
}
|
||||
|
||||
scoped_ptr<CriticalSectionWrapper> crit_;
|
||||
scoped_ptr<ConditionVariableWrapper> cv_;
|
||||
TraceLevel level_ GUARDED_BY(crit_);
|
||||
std::ostringstream expected_log_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
TEST_F(LoggingTest, LogStream) {
|
||||
{
|
||||
CriticalSectionScoped cs(crit_.get());
|
||||
level_ = kTraceWarning;
|
||||
std::string msg = "Important message";
|
||||
expected_log_ << "(logging_unittest.cc:" << __LINE__ + 1 << "): " << msg;
|
||||
LOG(LS_WARNING) << msg;
|
||||
cv_->SleepCS(*crit_.get(), 2000);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, LogFunctionError) {
|
||||
{
|
||||
CriticalSectionScoped cs(crit_.get());
|
||||
int bar = 42;
|
||||
int baz = 99;
|
||||
level_ = kTraceError;
|
||||
expected_log_ << "(logging_unittest.cc:" << __LINE__ + 2
|
||||
<< "): Foo failed: bar=" << bar << ", baz=" << baz;
|
||||
LOG_FERR2(LS_ERROR, Foo, bar, baz);
|
||||
cv_->SleepCS(*crit_.get(), 2000);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
226
jni/webrtc/system_wrappers/source/move.h
Normal file
226
jni/webrtc/system_wrappers/source/move.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/move.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_
|
||||
|
||||
// Macro with the boilerplate that makes a type move-only in C++03.
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
|
||||
// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
|
||||
// the first line in a class declaration.
|
||||
//
|
||||
// A class using this macro must call .Pass() (or somehow be an r-value already)
|
||||
// before it can be:
|
||||
//
|
||||
// * Passed as a function argument
|
||||
// * Used as the right-hand side of an assignment
|
||||
// * Returned from a function
|
||||
//
|
||||
// Each class will still need to define their own "move constructor" and "move
|
||||
// operator=" to make this useful. Here's an example of the macro, the move
|
||||
// constructor, and the move operator= from the scoped_ptr class:
|
||||
//
|
||||
// template <typename T>
|
||||
// class scoped_ptr {
|
||||
// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||
// public:
|
||||
// scoped_ptr(RValue& other) : ptr_(other.release()) { }
|
||||
// scoped_ptr& operator=(RValue& other) {
|
||||
// swap(other);
|
||||
// return *this;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Note that the constructor must NOT be marked explicit.
|
||||
//
|
||||
// For consistency, the second parameter to the macro should always be RValue
|
||||
// unless you have a strong reason to do otherwise. It is only exposed as a
|
||||
// macro parameter so that the move constructor and move operator= don't look
|
||||
// like they're using a phantom type.
|
||||
//
|
||||
//
|
||||
// HOW THIS WORKS
|
||||
//
|
||||
// For a thorough explanation of this technique, see:
|
||||
//
|
||||
// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
|
||||
//
|
||||
// The summary is that we take advantage of 2 properties:
|
||||
//
|
||||
// 1) non-const references will not bind to r-values.
|
||||
// 2) C++ can apply one user-defined conversion when initializing a
|
||||
// variable.
|
||||
//
|
||||
// The first lets us disable the copy constructor and assignment operator
|
||||
// by declaring private version of them with a non-const reference parameter.
|
||||
//
|
||||
// For l-values, direct initialization still fails like in
|
||||
// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
|
||||
// operators are private.
|
||||
//
|
||||
// For r-values, the situation is different. The copy constructor and
|
||||
// assignment operator are not viable due to (1), so we are trying to call
|
||||
// a non-existent constructor and non-existing operator= rather than a private
|
||||
// one. Since we have not committed an error quite yet, we can provide an
|
||||
// alternate conversion sequence and a constructor. We add
|
||||
//
|
||||
// * a private struct named "RValue"
|
||||
// * a user-defined conversion "operator RValue()"
|
||||
// * a "move constructor" and "move operator=" that take the RValue& as
|
||||
// their sole parameter.
|
||||
//
|
||||
// Only r-values will trigger this sequence and execute our "move constructor"
|
||||
// or "move operator=." L-values will match the private copy constructor and
|
||||
// operator= first giving a "private in this context" error. This combination
|
||||
// gives us a move-only type.
|
||||
//
|
||||
// For signaling a destructive transfer of data from an l-value, we provide a
|
||||
// method named Pass() which creates an r-value for the current instance
|
||||
// triggering the move constructor or move operator=.
|
||||
//
|
||||
// Other ways to get r-values is to use the result of an expression like a
|
||||
// function call.
|
||||
//
|
||||
// Here's an example with comments explaining what gets triggered where:
|
||||
//
|
||||
// class Foo {
|
||||
// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
|
||||
//
|
||||
// public:
|
||||
// ... API ...
|
||||
// Foo(RValue other); // Move constructor.
|
||||
// Foo& operator=(RValue rhs); // Move operator=
|
||||
// };
|
||||
//
|
||||
// Foo MakeFoo(); // Function that returns a Foo.
|
||||
//
|
||||
// Foo f;
|
||||
// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context.
|
||||
// Foo f_assign;
|
||||
// f_assign = f; // ERROR: operator=(Foo&) is private in this context.
|
||||
//
|
||||
//
|
||||
// Foo f(MakeFoo()); // R-value so alternate conversion executed.
|
||||
// Foo f_copy(f.Pass()); // R-value so alternate conversion executed.
|
||||
// f = f_copy.Pass(); // R-value so alternate conversion executed.
|
||||
//
|
||||
//
|
||||
// IMPLEMENTATION SUBTLETIES WITH RValue
|
||||
//
|
||||
// The RValue struct is just a container for a pointer back to the original
|
||||
// object. It should only ever be created as a temporary, and no external
|
||||
// class should ever declare it or use it in a parameter.
|
||||
//
|
||||
// It is tempting to want to use the RValue type in function parameters, but
|
||||
// excluding the limited usage here for the move constructor and move
|
||||
// operator=, doing so would mean that the function could take both r-values
|
||||
// and l-values equially which is unexpected. See COMPARED To Boost.Move for
|
||||
// more details.
|
||||
//
|
||||
// An alternate, and incorrect, implementation of the RValue class used by
|
||||
// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
|
||||
// is then used in place of RValue in the various operators. The RValue& is
|
||||
// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal
|
||||
// of never creating a temporary RValue struct even with optimizations
|
||||
// disabled. Also, by virtue of inheritance you can treat the RValue
|
||||
// reference as if it were the move-only type itself. Unfortunately,
|
||||
// using the result of this reinterpret_cast<> is actually undefined behavior
|
||||
// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
|
||||
// will generate non-working code.
|
||||
//
|
||||
// In optimized builds, both implementations generate the same assembly so we
|
||||
// choose the one that adheres to the standard.
|
||||
//
|
||||
//
|
||||
// WHY HAVE typedef void MoveOnlyTypeForCPP03
|
||||
//
|
||||
// Callback<>/Bind() needs to understand movable-but-not-copyable semantics
|
||||
// to call .Pass() appropriately when it is expected to transfer the value.
|
||||
// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check
|
||||
// easy and automatic in helper templates for Callback<>/Bind().
|
||||
// See IsMoveOnlyType template and its usage in base/callback_internal.h
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// COMPARED TO C++11
|
||||
//
|
||||
// In C++11, you would implement this functionality using an r-value reference
|
||||
// and our .Pass() method would be replaced with a call to std::move().
|
||||
//
|
||||
// This emulation also has a deficiency where it uses up the single
|
||||
// user-defined conversion allowed by C++ during initialization. This can
|
||||
// cause problems in some API edge cases. For instance, in scoped_ptr, it is
|
||||
// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
|
||||
// value of type scoped_ptr<Child> even if you add a constructor to
|
||||
// scoped_ptr<> that would make it look like it should work. C++11 does not
|
||||
// have this deficiency.
|
||||
//
|
||||
//
|
||||
// COMPARED TO Boost.Move
|
||||
//
|
||||
// Our implementation similar to Boost.Move, but we keep the RValue struct
|
||||
// private to the move-only type, and we don't use the reinterpret_cast<> hack.
|
||||
//
|
||||
// In Boost.Move, RValue is the boost::rv<> template. This type can be used
|
||||
// when writing APIs like:
|
||||
//
|
||||
// void MyFunc(boost::rv<Foo>& f)
|
||||
//
|
||||
// that can take advantage of rv<> to avoid extra copies of a type. However you
|
||||
// would still be able to call this version of MyFunc with an l-value:
|
||||
//
|
||||
// Foo f;
|
||||
// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass().
|
||||
//
|
||||
// unless someone is very careful to also declare a parallel override like:
|
||||
//
|
||||
// void MyFunc(const Foo& f)
|
||||
//
|
||||
// that would catch the l-values first. This was declared unsafe in C++11 and
|
||||
// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot
|
||||
// ensure this in C++03.
|
||||
//
|
||||
// Since we have no need for writing such APIs yet, our implementation keeps
|
||||
// RValue private and uses a .Pass() method to do the conversion instead of
|
||||
// trying to write a version of "std::move()." Writing an API like std::move()
|
||||
// would require the RValue struct to be public.
|
||||
//
|
||||
//
|
||||
// CAVEATS
|
||||
//
|
||||
// If you include a move-only type as a field inside a class that does not
|
||||
// explicitly declare a copy constructor, the containing class's implicit
|
||||
// copy constructor will change from Containing(const Containing&) to
|
||||
// Containing(Containing&). This can cause some unexpected errors.
|
||||
//
|
||||
// http://llvm.org/bugs/show_bug.cgi?id=11528
|
||||
//
|
||||
// The workaround is to explicitly declare your copy constructor.
|
||||
//
|
||||
#define WEBRTC_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 // WEBRTC_SYSTEM_WRAPPERS_INTEFACE_MOVE_H_
|
150
jni/webrtc/system_wrappers/source/rtp_to_ntp.cc
Normal file
150
jni/webrtc/system_wrappers/source/rtp_to_ntp.cc
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rtp_to_ntp.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RtcpMeasurement::RtcpMeasurement()
|
||||
: ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {}
|
||||
|
||||
RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac,
|
||||
uint32_t timestamp)
|
||||
: ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {}
|
||||
|
||||
// Calculates the RTP timestamp frequency from two pairs of NTP and RTP
|
||||
// timestamps.
|
||||
bool CalculateFrequency(
|
||||
int64_t rtcp_ntp_ms1,
|
||||
uint32_t rtp_timestamp1,
|
||||
int64_t rtcp_ntp_ms2,
|
||||
uint32_t rtp_timestamp2,
|
||||
double* frequency_khz) {
|
||||
if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) {
|
||||
return false;
|
||||
}
|
||||
*frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) /
|
||||
static_cast<double>(rtcp_ntp_ms1 - rtcp_ntp_ms2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Detects if there has been a wraparound between |old_timestamp| and
|
||||
// |new_timestamp|, and compensates by adding 2^32 if that is the case.
|
||||
bool CompensateForWrapAround(uint32_t new_timestamp,
|
||||
uint32_t old_timestamp,
|
||||
int64_t* compensated_timestamp) {
|
||||
assert(compensated_timestamp);
|
||||
int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp);
|
||||
if (wraps < 0) {
|
||||
// Reordering, don't use this packet.
|
||||
return false;
|
||||
}
|
||||
*compensated_timestamp = new_timestamp + (wraps << 32);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdateRtcpList(uint32_t ntp_secs,
|
||||
uint32_t ntp_frac,
|
||||
uint32_t rtp_timestamp,
|
||||
RtcpList* rtcp_list,
|
||||
bool* new_rtcp_sr) {
|
||||
*new_rtcp_sr = false;
|
||||
if (ntp_secs == 0 && ntp_frac == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RtcpMeasurement measurement;
|
||||
measurement.ntp_secs = ntp_secs;
|
||||
measurement.ntp_frac = ntp_frac;
|
||||
measurement.rtp_timestamp = rtp_timestamp;
|
||||
|
||||
for (RtcpList::iterator it = rtcp_list->begin();
|
||||
it != rtcp_list->end(); ++it) {
|
||||
if (measurement.ntp_secs == (*it).ntp_secs &&
|
||||
measurement.ntp_frac == (*it).ntp_frac) {
|
||||
// This RTCP has already been added to the list.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We need two RTCP SR reports to map between RTP and NTP. More than two will
|
||||
// not improve the mapping.
|
||||
if (rtcp_list->size() == 2) {
|
||||
rtcp_list->pop_back();
|
||||
}
|
||||
rtcp_list->push_front(measurement);
|
||||
*new_rtcp_sr = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp
|
||||
// pairs in |rtcp|. The converted timestamp is returned in
|
||||
// |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP
|
||||
// timestamps and returns false if it can't do the conversion due to reordering.
|
||||
bool RtpToNtpMs(int64_t rtp_timestamp,
|
||||
const RtcpList& rtcp,
|
||||
int64_t* rtp_timestamp_in_ms) {
|
||||
assert(rtcp.size() == 2);
|
||||
int64_t rtcp_ntp_ms_new = Clock::NtpToMs(rtcp.front().ntp_secs,
|
||||
rtcp.front().ntp_frac);
|
||||
int64_t rtcp_ntp_ms_old = Clock::NtpToMs(rtcp.back().ntp_secs,
|
||||
rtcp.back().ntp_frac);
|
||||
int64_t rtcp_timestamp_new = rtcp.front().rtp_timestamp;
|
||||
int64_t rtcp_timestamp_old = rtcp.back().rtp_timestamp;
|
||||
if (!CompensateForWrapAround(rtcp_timestamp_new,
|
||||
rtcp_timestamp_old,
|
||||
&rtcp_timestamp_new)) {
|
||||
return false;
|
||||
}
|
||||
double freq_khz;
|
||||
if (!CalculateFrequency(rtcp_ntp_ms_new,
|
||||
rtcp_timestamp_new,
|
||||
rtcp_ntp_ms_old,
|
||||
rtcp_timestamp_old,
|
||||
&freq_khz)) {
|
||||
return false;
|
||||
}
|
||||
double offset = rtcp_timestamp_new - freq_khz * rtcp_ntp_ms_new;
|
||||
int64_t rtp_timestamp_unwrapped;
|
||||
if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old,
|
||||
&rtp_timestamp_unwrapped)) {
|
||||
return false;
|
||||
}
|
||||
double rtp_timestamp_ntp_ms = (static_cast<double>(rtp_timestamp_unwrapped) -
|
||||
offset) / freq_khz + 0.5f;
|
||||
if (rtp_timestamp_ntp_ms < 0) {
|
||||
return false;
|
||||
}
|
||||
*rtp_timestamp_in_ms = rtp_timestamp_ntp_ms;
|
||||
return true;
|
||||
}
|
||||
|
||||
int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) {
|
||||
if (new_timestamp < old_timestamp) {
|
||||
// This difference should be less than -2^31 if we have had a wrap around
|
||||
// (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
|
||||
// cast to a int32_t, it should be positive.
|
||||
if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) {
|
||||
// Forward wrap around.
|
||||
return 1;
|
||||
}
|
||||
} else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) {
|
||||
// This difference should be less than -2^31 if we have had a backward wrap
|
||||
// around. Since it is cast to a int32_t, it should be positive.
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
146
jni/webrtc/system_wrappers/source/rtp_to_ntp_unittest.cc
Normal file
146
jni/webrtc/system_wrappers/source/rtp_to_ntp_unittest.cc
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/rtp_to_ntp.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(WrapAroundTests, NoWrap) {
|
||||
EXPECT_EQ(0, CheckForWrapArounds(0xFFFFFFFF, 0xFFFFFFFE));
|
||||
EXPECT_EQ(0, CheckForWrapArounds(1, 0));
|
||||
EXPECT_EQ(0, CheckForWrapArounds(0x00010000, 0x0000FFFF));
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, ForwardWrap) {
|
||||
EXPECT_EQ(1, CheckForWrapArounds(0, 0xFFFFFFFF));
|
||||
EXPECT_EQ(1, CheckForWrapArounds(0, 0xFFFF0000));
|
||||
EXPECT_EQ(1, CheckForWrapArounds(0x0000FFFF, 0xFFFFFFFF));
|
||||
EXPECT_EQ(1, CheckForWrapArounds(0x0000FFFF, 0xFFFF0000));
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, BackwardWrap) {
|
||||
EXPECT_EQ(-1, CheckForWrapArounds(0xFFFFFFFF, 0));
|
||||
EXPECT_EQ(-1, CheckForWrapArounds(0xFFFF0000, 0));
|
||||
EXPECT_EQ(-1, CheckForWrapArounds(0xFFFFFFFF, 0x0000FFFF));
|
||||
EXPECT_EQ(-1, CheckForWrapArounds(0xFFFF0000, 0x0000FFFF));
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, OldRtcpWrapped) {
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0;
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp -= kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp -= kTimestampTicksPerMs;
|
||||
int64_t timestamp_in_ms = -1;
|
||||
// This expected to fail since it's highly unlikely that the older RTCP
|
||||
// has a much smaller RTP timestamp than the newer.
|
||||
EXPECT_FALSE(RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms));
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, NewRtcpWrapped) {
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0xFFFFFFFF;
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
int64_t timestamp_in_ms = -1;
|
||||
EXPECT_TRUE(RtpToNtpMs(rtcp.back().rtp_timestamp, rtcp, ×tamp_in_ms));
|
||||
// Since this RTP packet has the same timestamp as the RTCP packet constructed
|
||||
// at time 0 it should be mapped to 0 as well.
|
||||
EXPECT_EQ(0, timestamp_in_ms);
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, RtpWrapped) {
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0xFFFFFFFF - 2 * kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += kTimestampTicksPerMs;
|
||||
int64_t timestamp_in_ms = -1;
|
||||
EXPECT_TRUE(RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms));
|
||||
// Since this RTP packet has the same timestamp as the RTCP packet constructed
|
||||
// at time 0 it should be mapped to 0 as well.
|
||||
EXPECT_EQ(2, timestamp_in_ms);
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, OldRtp_RtcpsWrapped) {
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp -= 2*kTimestampTicksPerMs;
|
||||
int64_t timestamp_in_ms = -1;
|
||||
EXPECT_FALSE(RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms));
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) {
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0xFFFFFFFF;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp -= kTimestampTicksPerMs;
|
||||
int64_t timestamp_in_ms = -1;
|
||||
EXPECT_TRUE(RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms));
|
||||
// Constructed at the same time as the first RTCP and should therefore be
|
||||
// mapped to zero.
|
||||
EXPECT_EQ(0, timestamp_in_ms);
|
||||
}
|
||||
|
||||
TEST(WrapAroundTests, OldRtp_OldRtcpWrapped) {
|
||||
const uint32_t kOneMsInNtpFrac = 4294967;
|
||||
const uint32_t kTimestampTicksPerMs = 90;
|
||||
RtcpList rtcp;
|
||||
uint32_t ntp_sec = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t timestamp = 0;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp -= kTimestampTicksPerMs;
|
||||
rtcp.push_front(RtcpMeasurement(ntp_sec, ntp_frac, timestamp));
|
||||
ntp_frac += kOneMsInNtpFrac;
|
||||
timestamp += 2*kTimestampTicksPerMs;
|
||||
int64_t timestamp_in_ms = -1;
|
||||
EXPECT_FALSE(RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms));
|
||||
}
|
||||
}; // namespace webrtc
|
37
jni/webrtc/system_wrappers/source/rw_lock.cc
Normal file
37
jni/webrtc/system_wrappers/source/rw_lock.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
|
||||
#include "webrtc/system_wrappers/source/rw_lock_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockWrapper* RWLockWrapper::CreateRWLock() {
|
||||
#ifdef _WIN32
|
||||
// Native implementation is faster, so use that if available.
|
||||
RWLockWrapper* lock = RWLockWin::Create();
|
||||
if (lock) {
|
||||
return lock;
|
||||
}
|
||||
return new RWLockGeneric();
|
||||
#else
|
||||
return RWLockPosix::Create();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
77
jni/webrtc/system_wrappers/source/rw_lock_generic.cc
Normal file
77
jni/webrtc/system_wrappers/source/rw_lock_generic.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockGeneric::RWLockGeneric()
|
||||
: readers_active_(0),
|
||||
writer_active_(false),
|
||||
readers_waiting_(0),
|
||||
writers_waiting_(0) {
|
||||
critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
}
|
||||
|
||||
RWLockGeneric::~RWLockGeneric() {
|
||||
delete write_condition_;
|
||||
delete read_condition_;
|
||||
delete critical_section_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || readers_active_ > 0) {
|
||||
++writers_waiting_;
|
||||
while (writer_active_ || readers_active_ > 0) {
|
||||
write_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--writers_waiting_;
|
||||
}
|
||||
writer_active_ = true;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
writer_active_ = false;
|
||||
if (writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
} else if (readers_waiting_ > 0) {
|
||||
read_condition_->WakeAll();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || writers_waiting_ > 0) {
|
||||
++readers_waiting_;
|
||||
|
||||
while (writer_active_ || writers_waiting_ > 0) {
|
||||
read_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--readers_waiting_;
|
||||
}
|
||||
++readers_active_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
--readers_active_;
|
||||
if (readers_active_ == 0 && writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
46
jni/webrtc/system_wrappers/source/rw_lock_generic.h
Normal file
46
jni/webrtc/system_wrappers/source/rw_lock_generic.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
class RWLockGeneric : public RWLockWrapper {
|
||||
public:
|
||||
RWLockGeneric();
|
||||
virtual ~RWLockGeneric();
|
||||
|
||||
virtual void AcquireLockExclusive() OVERRIDE;
|
||||
virtual void ReleaseLockExclusive() OVERRIDE;
|
||||
|
||||
virtual void AcquireLockShared() OVERRIDE;
|
||||
virtual void ReleaseLockShared() OVERRIDE;
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* critical_section_;
|
||||
ConditionVariableWrapper* read_condition_;
|
||||
ConditionVariableWrapper* write_condition_;
|
||||
|
||||
int readers_active_;
|
||||
bool writer_active_;
|
||||
int readers_waiting_;
|
||||
int writers_waiting_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
51
jni/webrtc/system_wrappers/source/rw_lock_posix.cc
Normal file
51
jni/webrtc/system_wrappers/source/rw_lock_posix.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockPosix::RWLockPosix() : lock_() {
|
||||
}
|
||||
|
||||
RWLockPosix::~RWLockPosix() {
|
||||
pthread_rwlock_destroy(&lock_);
|
||||
}
|
||||
|
||||
RWLockPosix* RWLockPosix::Create() {
|
||||
RWLockPosix* ret_val = new RWLockPosix();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool RWLockPosix::Init() {
|
||||
return pthread_rwlock_init(&lock_, 0) == 0;
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockExclusive() {
|
||||
pthread_rwlock_wrlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockExclusive() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockShared() {
|
||||
pthread_rwlock_rdlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockShared() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
jni/webrtc/system_wrappers/source/rw_lock_posix.h
Normal file
41
jni/webrtc/system_wrappers/source/rw_lock_posix.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockPosix : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockPosix* Create();
|
||||
virtual ~RWLockPosix();
|
||||
|
||||
virtual void AcquireLockExclusive() OVERRIDE;
|
||||
virtual void ReleaseLockExclusive() OVERRIDE;
|
||||
|
||||
virtual void AcquireLockShared() OVERRIDE;
|
||||
virtual void ReleaseLockShared() OVERRIDE;
|
||||
|
||||
private:
|
||||
RWLockPosix();
|
||||
bool Init();
|
||||
|
||||
pthread_rwlock_t lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
97
jni/webrtc/system_wrappers/source/rw_lock_win.cc
Normal file
97
jni/webrtc/system_wrappers/source/rw_lock_win.cc
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_win.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static bool native_rw_locks_supported = false;
|
||||
static bool module_load_attempted = false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
typedef void (WINAPI* InitializeSRWLock)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockExclusive)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockExclusive)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockShared)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockShared)(PSRWLOCK);
|
||||
|
||||
InitializeSRWLock initialize_srw_lock;
|
||||
AcquireSRWLockExclusive acquire_srw_lock_exclusive;
|
||||
AcquireSRWLockShared acquire_srw_lock_shared;
|
||||
ReleaseSRWLockShared release_srw_lock_shared;
|
||||
ReleaseSRWLockExclusive release_srw_lock_exclusive;
|
||||
|
||||
RWLockWin::RWLockWin() {
|
||||
initialize_srw_lock(&lock_);
|
||||
}
|
||||
|
||||
RWLockWin* RWLockWin::Create() {
|
||||
if (!LoadModule()) {
|
||||
return NULL;
|
||||
}
|
||||
return new RWLockWin();
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockExclusive() {
|
||||
acquire_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockExclusive() {
|
||||
release_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockShared() {
|
||||
acquire_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockShared() {
|
||||
release_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
bool RWLockWin::LoadModule() {
|
||||
if (module_load_attempted) {
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
module_load_attempted = true;
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if (!library) {
|
||||
return false;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
initialize_srw_lock =
|
||||
(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");
|
||||
|
||||
acquire_srw_lock_exclusive =
|
||||
(AcquireSRWLockExclusive)GetProcAddress(library,
|
||||
"AcquireSRWLockExclusive");
|
||||
release_srw_lock_exclusive =
|
||||
(ReleaseSRWLockExclusive)GetProcAddress(library,
|
||||
"ReleaseSRWLockExclusive");
|
||||
acquire_srw_lock_shared =
|
||||
(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
|
||||
release_srw_lock_shared =
|
||||
(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");
|
||||
|
||||
if (initialize_srw_lock && acquire_srw_lock_exclusive &&
|
||||
release_srw_lock_exclusive && acquire_srw_lock_shared &&
|
||||
release_srw_lock_shared) {
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Native RW Lock");
|
||||
native_rw_locks_supported = true;
|
||||
}
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
40
jni/webrtc/system_wrappers/source/rw_lock_win.h
Normal file
40
jni/webrtc/system_wrappers/source/rw_lock_win.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWin : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockWin* Create();
|
||||
~RWLockWin() {}
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
private:
|
||||
RWLockWin();
|
||||
static bool LoadModule();
|
||||
|
||||
SRWLOCK lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
328
jni/webrtc/system_wrappers/source/scoped_vector_unittest.cc
Normal file
328
jni/webrtc/system_wrappers/source/scoped_vector_unittest.cc
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/memory/scoped_vector_unittest.cc
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_vector.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
// The LifeCycleObject notifies its Observer upon construction & destruction.
|
||||
class LifeCycleObject {
|
||||
public:
|
||||
class Observer {
|
||||
public:
|
||||
virtual void OnLifeCycleConstruct(LifeCycleObject* o) = 0;
|
||||
virtual void OnLifeCycleDestroy(LifeCycleObject* o) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Observer() {}
|
||||
};
|
||||
|
||||
~LifeCycleObject() {
|
||||
observer_->OnLifeCycleDestroy(this);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LifeCycleWatcher;
|
||||
|
||||
explicit LifeCycleObject(Observer* observer)
|
||||
: observer_(observer) {
|
||||
observer_->OnLifeCycleConstruct(this);
|
||||
}
|
||||
|
||||
Observer* observer_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LifeCycleObject);
|
||||
};
|
||||
|
||||
// The life cycle states we care about for the purposes of testing ScopedVector
|
||||
// against objects.
|
||||
enum LifeCycleState {
|
||||
LC_INITIAL,
|
||||
LC_CONSTRUCTED,
|
||||
LC_DESTROYED,
|
||||
};
|
||||
|
||||
// Because we wish to watch the life cycle of an object being constructed and
|
||||
// destroyed, and further wish to test expectations against the state of that
|
||||
// object, we cannot save state in that object itself. Instead, we use this
|
||||
// pairing of the watcher, which observes the object and notifies of
|
||||
// construction & destruction. Since we also may be testing assumptions about
|
||||
// things not getting freed, this class also acts like a scoping object and
|
||||
// deletes the |constructed_life_cycle_object_|, if any when the
|
||||
// LifeCycleWatcher is destroyed. To keep this simple, the only expected state
|
||||
// changes are:
|
||||
// INITIAL -> CONSTRUCTED -> DESTROYED.
|
||||
// Anything more complicated than that should start another test.
|
||||
class LifeCycleWatcher : public LifeCycleObject::Observer {
|
||||
public:
|
||||
LifeCycleWatcher() : life_cycle_state_(LC_INITIAL) {}
|
||||
virtual ~LifeCycleWatcher() {}
|
||||
|
||||
// Assert INITIAL -> CONSTRUCTED and no LifeCycleObject associated with this
|
||||
// LifeCycleWatcher.
|
||||
virtual void OnLifeCycleConstruct(LifeCycleObject* object) OVERRIDE {
|
||||
ASSERT_EQ(LC_INITIAL, life_cycle_state_);
|
||||
ASSERT_EQ(NULL, constructed_life_cycle_object_.get());
|
||||
life_cycle_state_ = LC_CONSTRUCTED;
|
||||
constructed_life_cycle_object_.reset(object);
|
||||
}
|
||||
|
||||
// Assert CONSTRUCTED -> DESTROYED and the |object| being destroyed is the
|
||||
// same one we saw constructed.
|
||||
virtual void OnLifeCycleDestroy(LifeCycleObject* object) OVERRIDE {
|
||||
ASSERT_EQ(LC_CONSTRUCTED, life_cycle_state_);
|
||||
LifeCycleObject* constructed_life_cycle_object =
|
||||
constructed_life_cycle_object_.release();
|
||||
ASSERT_EQ(constructed_life_cycle_object, object);
|
||||
life_cycle_state_ = LC_DESTROYED;
|
||||
}
|
||||
|
||||
LifeCycleState life_cycle_state() const { return life_cycle_state_; }
|
||||
|
||||
// Factory method for creating a new LifeCycleObject tied to this
|
||||
// LifeCycleWatcher.
|
||||
LifeCycleObject* NewLifeCycleObject() {
|
||||
return new LifeCycleObject(this);
|
||||
}
|
||||
|
||||
// Returns true iff |object| is the same object that this watcher is tracking.
|
||||
bool IsWatching(LifeCycleObject* object) const {
|
||||
return object == constructed_life_cycle_object_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
LifeCycleState life_cycle_state_;
|
||||
scoped_ptr<LifeCycleObject> constructed_life_cycle_object_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LifeCycleWatcher);
|
||||
};
|
||||
|
||||
TEST(ScopedVectorTest, LifeCycleWatcher) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
LifeCycleObject* object = watcher.NewLifeCycleObject();
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
delete object;
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, PopBack) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
scoped_vector.pop_back();
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(scoped_vector.empty());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, Clear) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
scoped_vector.clear();
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(scoped_vector.empty());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, WeakClear) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
scoped_vector.weak_clear();
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(scoped_vector.empty());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, ResizeShrink) {
|
||||
LifeCycleWatcher first_watcher;
|
||||
EXPECT_EQ(LC_INITIAL, first_watcher.life_cycle_state());
|
||||
LifeCycleWatcher second_watcher;
|
||||
EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state());
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
|
||||
scoped_vector.push_back(first_watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
|
||||
EXPECT_EQ(LC_INITIAL, second_watcher.life_cycle_state());
|
||||
EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0]));
|
||||
EXPECT_FALSE(second_watcher.IsWatching(scoped_vector[0]));
|
||||
|
||||
scoped_vector.push_back(second_watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, second_watcher.life_cycle_state());
|
||||
EXPECT_FALSE(first_watcher.IsWatching(scoped_vector[1]));
|
||||
EXPECT_TRUE(second_watcher.IsWatching(scoped_vector[1]));
|
||||
|
||||
// Test that shrinking a vector deletes elements in the disappearing range.
|
||||
scoped_vector.resize(1);
|
||||
EXPECT_EQ(LC_CONSTRUCTED, first_watcher.life_cycle_state());
|
||||
EXPECT_EQ(LC_DESTROYED, second_watcher.life_cycle_state());
|
||||
EXPECT_EQ(1u, scoped_vector.size());
|
||||
EXPECT_TRUE(first_watcher.IsWatching(scoped_vector[0]));
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, ResizeGrow) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
|
||||
scoped_vector.resize(5);
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
ASSERT_EQ(5u, scoped_vector.size());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector[0]));
|
||||
EXPECT_FALSE(watcher.IsWatching(scoped_vector[1]));
|
||||
EXPECT_FALSE(watcher.IsWatching(scoped_vector[2]));
|
||||
EXPECT_FALSE(watcher.IsWatching(scoped_vector[3]));
|
||||
EXPECT_FALSE(watcher.IsWatching(scoped_vector[4]));
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, Scope) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
{
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
}
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, MoveConstruct) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
{
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
EXPECT_FALSE(scoped_vector.empty());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
|
||||
ScopedVector<LifeCycleObject> scoped_vector_copy(scoped_vector.Pass());
|
||||
EXPECT_TRUE(scoped_vector.empty());
|
||||
EXPECT_FALSE(scoped_vector_copy.empty());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector_copy.back()));
|
||||
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
}
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
}
|
||||
|
||||
TEST(ScopedVectorTest, MoveAssign) {
|
||||
LifeCycleWatcher watcher;
|
||||
EXPECT_EQ(LC_INITIAL, watcher.life_cycle_state());
|
||||
{
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.push_back(watcher.NewLifeCycleObject());
|
||||
ScopedVector<LifeCycleObject> scoped_vector_assign;
|
||||
EXPECT_FALSE(scoped_vector.empty());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector.back()));
|
||||
|
||||
scoped_vector_assign = scoped_vector.Pass();
|
||||
EXPECT_TRUE(scoped_vector.empty());
|
||||
EXPECT_FALSE(scoped_vector_assign.empty());
|
||||
EXPECT_TRUE(watcher.IsWatching(scoped_vector_assign.back()));
|
||||
|
||||
EXPECT_EQ(LC_CONSTRUCTED, watcher.life_cycle_state());
|
||||
}
|
||||
EXPECT_EQ(LC_DESTROYED, watcher.life_cycle_state());
|
||||
}
|
||||
|
||||
class DeleteCounter {
|
||||
public:
|
||||
explicit DeleteCounter(int* deletes)
|
||||
: deletes_(deletes) {
|
||||
}
|
||||
|
||||
~DeleteCounter() {
|
||||
(*deletes_)++;
|
||||
}
|
||||
|
||||
void VoidMethod0() {}
|
||||
|
||||
private:
|
||||
int* const deletes_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DeleteCounter);
|
||||
};
|
||||
|
||||
// This class is used in place of Chromium's base::Callback.
|
||||
template <typename T>
|
||||
class PassThru {
|
||||
public:
|
||||
explicit PassThru(ScopedVector<T> scoper) : scoper_(scoper.Pass()) {}
|
||||
|
||||
ScopedVector<T> Run() {
|
||||
return scoper_.Pass();
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedVector<T> scoper_;
|
||||
};
|
||||
|
||||
TEST(ScopedVectorTest, Passed) {
|
||||
int deletes = 0;
|
||||
ScopedVector<DeleteCounter> deleter_vector;
|
||||
deleter_vector.push_back(new DeleteCounter(&deletes));
|
||||
EXPECT_EQ(0, deletes);
|
||||
PassThru<DeleteCounter> pass_thru(deleter_vector.Pass());
|
||||
EXPECT_EQ(0, deletes);
|
||||
ScopedVector<DeleteCounter> result = pass_thru.Run();
|
||||
EXPECT_EQ(0, deletes);
|
||||
result.clear();
|
||||
EXPECT_EQ(1, deletes);
|
||||
};
|
||||
|
||||
TEST(ScopedVectorTest, InsertRange) {
|
||||
LifeCycleWatcher watchers[5];
|
||||
size_t watchers_size = sizeof(watchers) / sizeof(*watchers);
|
||||
|
||||
std::vector<LifeCycleObject*> vec;
|
||||
for (LifeCycleWatcher* it = watchers; it != watchers + watchers_size;
|
||||
++it) {
|
||||
EXPECT_EQ(LC_INITIAL, it->life_cycle_state());
|
||||
vec.push_back(it->NewLifeCycleObject());
|
||||
EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
|
||||
}
|
||||
// Start scope for ScopedVector.
|
||||
{
|
||||
ScopedVector<LifeCycleObject> scoped_vector;
|
||||
scoped_vector.insert(scoped_vector.end(), vec.begin() + 1, vec.begin() + 3);
|
||||
for (LifeCycleWatcher* it = watchers; it != watchers + watchers_size;
|
||||
++it)
|
||||
EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
|
||||
}
|
||||
for (LifeCycleWatcher* it = watchers; it != watchers + 1; ++it)
|
||||
EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
|
||||
for (LifeCycleWatcher* it = watchers + 1; it != watchers + 3; ++it)
|
||||
EXPECT_EQ(LC_DESTROYED, it->life_cycle_state());
|
||||
for (LifeCycleWatcher* it = watchers + 3; it != watchers + watchers_size;
|
||||
++it)
|
||||
EXPECT_EQ(LC_CONSTRUCTED, it->life_cycle_state());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
108
jni/webrtc/system_wrappers/source/set_thread_name_win.h
Normal file
108
jni/webrtc/system_wrappers/source/set_thread_name_win.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Source:
|
||||
http://msdn.microsoft.com/en-us/cc300389.aspx#P
|
||||
|
||||
License:
|
||||
This license governs use of code marked as “sample” or “example” available on
|
||||
this web site without a license agreement, as provided under the section above
|
||||
titled “NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.” If you use
|
||||
such code (the “software”), you accept this license. If you do not accept the
|
||||
license, do not use the software.
|
||||
|
||||
1. Definitions
|
||||
|
||||
The terms “reproduce,” “reproduction,” “derivative works,” and “distribution”
|
||||
have the same meaning here as under U.S. copyright law.
|
||||
|
||||
A “contribution” is the original software, or any additions or changes to the
|
||||
software.
|
||||
|
||||
A “contributor” is any person that distributes its contribution under this
|
||||
license.
|
||||
|
||||
“Licensed patents” are a contributor’s patent claims that read directly on its
|
||||
contribution.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
(A) Copyright Grant - Subject to the terms of this license, including the
|
||||
license conditions and limitations in section 3, each contributor grants you a
|
||||
non-exclusive, worldwide, royalty-free copyright license to reproduce its
|
||||
contribution, prepare derivative works of its contribution, and distribute its
|
||||
contribution or any derivative works that you create.
|
||||
|
||||
(B) Patent Grant - Subject to the terms of this license, including the license
|
||||
conditions and limitations in section 3, each contributor grants you a
|
||||
non-exclusive, worldwide, royalty-free license under its licensed patents to
|
||||
make, have made, use, sell, offer for sale, import, and/or otherwise dispose
|
||||
of its contribution in the software or derivative works of the contribution in
|
||||
the software.
|
||||
|
||||
3. Conditions and Limitations
|
||||
|
||||
(A) No Trademark License- This license does not grant you rights to use any
|
||||
contributors’ name, logo, or trademarks.
|
||||
|
||||
(B) If you bring a patent claim against any contributor over patents that you
|
||||
claim are infringed by the software, your patent license from such contributor
|
||||
to the software ends automatically.
|
||||
|
||||
(C) If you distribute any portion of the software, you must retain all
|
||||
copyright, patent, trademark, and attribution notices that are present in the
|
||||
software.
|
||||
|
||||
(D) If you distribute any portion of the software in source code form, you may
|
||||
do so only under this license by including a complete copy of this license
|
||||
with your distribution. If you distribute any portion of the software in
|
||||
compiled or object code form, you may only do so under a license that complies
|
||||
with this license.
|
||||
|
||||
(E) The software is licensed “as-is.” You bear the risk of using it. The
|
||||
contributors give no express warranties, guarantees or conditions. You may
|
||||
have additional consumer rights under your local laws which this license
|
||||
cannot change. To the extent permitted under your local laws, the contributors
|
||||
exclude the implied warranties of merchantability, fitness for a particular
|
||||
purpose and non-infringement.
|
||||
|
||||
(F) Platform Limitation - The licenses granted in sections 2(A) and 2(B)
|
||||
extend only to the software or derivative works that you create that run on a
|
||||
Microsoft Windows operating system product.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original code can be found here:
|
||||
* http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct THREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
LPCSTR szName; // pointer to name (in user addr space)
|
||||
DWORD dwThreadID; // thread ID (-1 = caller thread)
|
||||
DWORD dwFlags; // reserved for future use, must be zero
|
||||
};
|
||||
|
||||
void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
|
||||
(ULONG_PTR*)&info);
|
||||
}
|
||||
__except (EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user