Update to current webrtc library
This is from the upstream library commit id 3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium 88.0.4290.1.
This commit is contained in:
@ -6,218 +6,138 @@
|
||||
# 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")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
import("../webrtc.gni")
|
||||
|
||||
static_library("system_wrappers") {
|
||||
rtc_library("system_wrappers") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"include/aligned_array.h",
|
||||
"include/aligned_malloc.h",
|
||||
"include/atomic32.h",
|
||||
"include/clock.h",
|
||||
"include/condition_variable_wrapper.h",
|
||||
"include/cpu_features_wrapper.h",
|
||||
"include/cpu_info.h",
|
||||
"include/critical_section_wrapper.h",
|
||||
"include/data_log.h",
|
||||
"include/data_log_c.h",
|
||||
"include/data_log_impl.h",
|
||||
"include/event_tracer.h",
|
||||
"include/event_wrapper.h",
|
||||
"include/field_trial.h",
|
||||
"include/file_wrapper.h",
|
||||
"include/fix_interlocked_exchange_pointer_win.h",
|
||||
"include/logging.h",
|
||||
"include/metrics.h",
|
||||
"include/ref_count.h",
|
||||
"include/rtp_to_ntp.h",
|
||||
"include/rw_lock_wrapper.h",
|
||||
"include/scoped_vector.h",
|
||||
"include/ntp_time.h",
|
||||
"include/rtp_to_ntp_estimator.h",
|
||||
"include/sleep.h",
|
||||
"include/sort.h",
|
||||
"include/static_instance.h",
|
||||
"include/stl_util.h",
|
||||
"include/stringize_macros.h",
|
||||
"include/thread_wrapper.h",
|
||||
"include/tick_util.h",
|
||||
"include/timestamp_extrapolator.h",
|
||||
"include/trace.h",
|
||||
"include/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_event_win.cc",
|
||||
"source/condition_variable_event_win.h",
|
||||
"source/condition_variable_native_win.cc",
|
||||
"source/condition_variable_native_win.h",
|
||||
"source/condition_variable_posix.cc",
|
||||
"source/condition_variable_posix.h",
|
||||
"source/cpu_features.cc",
|
||||
"source/cpu_info.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_timer_posix.cc",
|
||||
"source/event_timer_posix.h",
|
||||
"source/event_timer_win.cc",
|
||||
"source/event_timer_win.h",
|
||||
"source/event_tracer.cc",
|
||||
"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/rtp_to_ntp_estimator.cc",
|
||||
"source/sleep.cc",
|
||||
"source/sort.cc",
|
||||
"source/thread.cc",
|
||||
"source/thread_posix.cc",
|
||||
"source/thread_posix.h",
|
||||
"source/thread_win.cc",
|
||||
"source/thread_win.h",
|
||||
"source/tick_util.cc",
|
||||
"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" ]
|
||||
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
|
||||
if (rtc_enable_data_logging) {
|
||||
sources += [ "source/data_log.cc" ]
|
||||
} else {
|
||||
sources += [ "source/data_log_no_op.cc" ]
|
||||
}
|
||||
|
||||
defines = []
|
||||
libs = []
|
||||
deps = [
|
||||
"..:webrtc_common",
|
||||
":field_trial",
|
||||
"../api:array_view",
|
||||
"../api/units:timestamp",
|
||||
"../modules:module_api_public",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
"../rtc_base/synchronization:rw_lock_wrapper",
|
||||
"../rtc_base/system:arch",
|
||||
"../rtc_base/system:rtc_export",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"include/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" ]
|
||||
if (build_with_mozilla) {
|
||||
include_dirs = [
|
||||
"/config/external/nspr",
|
||||
"/nsprpub/lib/ds",
|
||||
"/nsprpub/pr/include",
|
||||
]
|
||||
} else {
|
||||
sources += [ "source/cpu_features_android.cc" ]
|
||||
deps += [ "//third_party/android_sdk:cpu_features" ]
|
||||
}
|
||||
|
||||
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",
|
||||
]
|
||||
if (is_linux || is_chromeos) {
|
||||
if (!build_with_chromium) {
|
||||
sources += [ "source/cpu_features_linux.cc" ]
|
||||
}
|
||||
|
||||
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.
|
||||
]
|
||||
# Windows needs ../rtc_base due to include of
|
||||
# webrtc/rtc_base/win32.h in source/clock.cc.
|
||||
deps += [ "../rtc_base:win32" ]
|
||||
}
|
||||
|
||||
deps += [ "../base:rtc_base_approved" ]
|
||||
deps += [
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_numerics",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("field_trial_default") {
|
||||
sources = [
|
||||
"include/field_trial_default.h",
|
||||
"source/field_trial_default.cc",
|
||||
]
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
|
||||
rtc_library("field_trial") {
|
||||
visibility = [ "*" ]
|
||||
public = [ "include/field_trial.h" ]
|
||||
sources = [ "source/field_trial.cc" ]
|
||||
if (rtc_exclude_field_trial_default) {
|
||||
defines = [ "WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT" ]
|
||||
}
|
||||
deps = [
|
||||
":system_wrappers",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:stringutils",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
|
||||
}
|
||||
|
||||
source_set("metrics_default") {
|
||||
sources = [
|
||||
"source/metrics_default.cc",
|
||||
]
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
|
||||
rtc_library("metrics") {
|
||||
visibility = [ "*" ]
|
||||
public = [ "include/metrics.h" ]
|
||||
sources = [ "source/metrics.cc" ]
|
||||
if (rtc_exclude_metrics_default) {
|
||||
defines = [ "WEBRTC_EXCLUDE_METRICS_DEFAULT" ]
|
||||
}
|
||||
deps = [
|
||||
":system_wrappers",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("system_wrappers_default") {
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
|
||||
deps = [
|
||||
":field_trial_default",
|
||||
":metrics_default",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
source_set("cpu_features_android") {
|
||||
if (rtc_include_tests) {
|
||||
rtc_test("system_wrappers_unittests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"source/cpu_features_android.c",
|
||||
"source/clock_unittest.cc",
|
||||
"source/field_trial_unittest.cc",
|
||||
"source/metrics_default_unittest.cc",
|
||||
"source/metrics_unittest.cc",
|
||||
"source/ntp_time_unittest.cc",
|
||||
"source/rtp_to_ntp_estimator_unittest.cc",
|
||||
]
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
deps = [
|
||||
"//third_party/android_tools:cpu_features",
|
||||
":field_trial",
|
||||
":metrics",
|
||||
":system_wrappers",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../test:rtc_expect_death",
|
||||
"../test:test_main",
|
||||
"../test:test_support",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_ALIGNED_ARRAY_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_ALIGNED_ARRAY_
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Wrapper class for aligned arrays. Every row (and the first dimension) are
|
||||
// aligned to the given byte alignment.
|
||||
template<typename T> class AlignedArray {
|
||||
public:
|
||||
AlignedArray(int rows, size_t cols, int alignment)
|
||||
: rows_(rows),
|
||||
cols_(cols),
|
||||
alignment_(alignment) {
|
||||
RTC_CHECK_GT(alignment_, 0);
|
||||
head_row_ = static_cast<T**>(AlignedMalloc(rows_ * sizeof(*head_row_),
|
||||
alignment_));
|
||||
for (int i = 0; i < rows_; ++i) {
|
||||
head_row_[i] = static_cast<T*>(AlignedMalloc(cols_ * sizeof(**head_row_),
|
||||
alignment_));
|
||||
}
|
||||
}
|
||||
|
||||
~AlignedArray() {
|
||||
for (int i = 0; i < rows_; ++i) {
|
||||
AlignedFree(head_row_[i]);
|
||||
}
|
||||
AlignedFree(head_row_);
|
||||
}
|
||||
|
||||
T* const* Array() {
|
||||
return head_row_;
|
||||
}
|
||||
|
||||
const T* const* Array() const {
|
||||
return head_row_;
|
||||
}
|
||||
|
||||
T* Row(int row) {
|
||||
RTC_CHECK_LE(row, rows_);
|
||||
return head_row_[row];
|
||||
}
|
||||
|
||||
const T* Row(int row) const {
|
||||
RTC_CHECK_LE(row, rows_);
|
||||
return head_row_[row];
|
||||
}
|
||||
|
||||
T& At(int row, size_t col) {
|
||||
RTC_CHECK_LE(col, cols_);
|
||||
return Row(row)[col];
|
||||
}
|
||||
|
||||
const T& At(int row, size_t col) const {
|
||||
RTC_CHECK_LE(col, cols_);
|
||||
return Row(row)[col];
|
||||
}
|
||||
|
||||
int rows() const {
|
||||
return rows_;
|
||||
}
|
||||
|
||||
size_t cols() const {
|
||||
return cols_;
|
||||
}
|
||||
|
||||
private:
|
||||
int rows_;
|
||||
size_t cols_;
|
||||
int alignment_;
|
||||
T** head_row_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_ALIGNED_ARRAY_
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_ALIGNED_MALLOC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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_INCLUDE_ALIGNED_MALLOC_H_
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_ASM_DEFINES_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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
|
||||
.private_extern _\name
|
||||
.endm
|
||||
.macro DEFINE_FUNCTION name
|
||||
_\name:
|
||||
.endm
|
||||
.macro CALL_FUNCTION name
|
||||
bl _\name
|
||||
.endm
|
||||
.macro GLOBAL_LABEL name
|
||||
.global _\name
|
||||
.private_extern _\name
|
||||
.endm
|
||||
#else
|
||||
.macro GLOBAL_FUNCTION name
|
||||
.global \name
|
||||
.hidden \name
|
||||
.endm
|
||||
.macro DEFINE_FUNCTION name
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.type \name,%function
|
||||
#endif
|
||||
\name:
|
||||
.endm
|
||||
.macro CALL_FUNCTION name
|
||||
bl \name
|
||||
.endm
|
||||
.macro GLOBAL_LABEL name
|
||||
.global \name
|
||||
.hidden \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_INCLUDE_ASM_DEFINES_H_
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_COMPILE_ASSERT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_COMPILE_ASSERT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#error "Only use this for C files. For C++, use static_assert."
|
||||
#endif
|
||||
|
||||
// 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_INCLUDE_COMPILE_ASSERT_H_
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_CONDITION_VARIABLE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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_INCLUDE_CONDITION_VARIABLE_WRAPPER_H_
|
@ -8,44 +8,35 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
namespace webrtc {
|
||||
|
||||
// List of features in x86.
|
||||
typedef enum {
|
||||
kSSE2,
|
||||
kSSE3
|
||||
} CPUFeature;
|
||||
typedef enum { kSSE2, kSSE3, kAVX2 } CPUFeature;
|
||||
|
||||
// List of features in ARM.
|
||||
enum {
|
||||
kCPUFeatureARMv7 = (1 << 0),
|
||||
kCPUFeatureVFPv3 = (1 << 1),
|
||||
kCPUFeatureNEON = (1 << 2),
|
||||
kCPUFeatureLDREXSTREX = (1 << 3)
|
||||
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;
|
||||
int GetCPUInfo(CPUFeature feature);
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
extern WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM;
|
||||
int GetCPUInfoNoASM(CPUFeature feature);
|
||||
|
||||
// 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);
|
||||
uint64_t GetCPUFeaturesARM(void);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_CRITICAL_SECTION_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CRITICAL_SECTION_WRAPPER_H_
|
||||
|
||||
// If the critical section is heavily contended it may be beneficial to use
|
||||
// read/write locks instead.
|
||||
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
#include "webrtc/common_types.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_INCLUDE_CRITICAL_SECTION_WRAPPER_H_
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_EVENT_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_EVENT_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
enum EventTypeWrapper {
|
||||
kEventSignaled = 1,
|
||||
kEventError = 2,
|
||||
kEventTimeout = 3
|
||||
};
|
||||
|
||||
#define WEBRTC_EVENT_INFINITE 0xffffffff
|
||||
|
||||
class EventTimerWrapper;
|
||||
|
||||
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;
|
||||
|
||||
// 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 reset the event 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.
|
||||
//
|
||||
// |max_time| is the maximum time to wait in milliseconds or
|
||||
// WEBRTC_EVENT_INFINITE to wait infinitely.
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time) = 0;
|
||||
};
|
||||
|
||||
class EventTimerWrapper : public EventWrapper {
|
||||
public:
|
||||
static EventTimerWrapper* Create();
|
||||
|
||||
// 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.
|
||||
//
|
||||
// |time| is in milliseconds.
|
||||
virtual bool StartTimer(bool periodic, unsigned long time) = 0;
|
||||
|
||||
virtual bool StopTimer() = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_EVENT_WRAPPER_H_
|
102
webrtc/system_wrappers/include/field_trial.h
Normal file
102
webrtc/system_wrappers/include/field_trial.h
Normal file
@ -0,0 +1,102 @@
|
||||
//
|
||||
// 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 SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
// Field trials allow webrtc clients (such as Chrome) to turn on feature code
|
||||
// in binaries out in the field and gather information with that.
|
||||
//
|
||||
// By default WebRTC provides an implementation of field trials that can be
|
||||
// found in system_wrappers/source/field_trial.cc. If clients want to provide
|
||||
// a custom version, they will have to:
|
||||
//
|
||||
// 1. Compile WebRTC defining the preprocessor macro
|
||||
// WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT (if GN is used this can be achieved
|
||||
// by setting the GN arg rtc_exclude_field_trial_default to true).
|
||||
// 2. Provide an implementation of:
|
||||
// std::string webrtc::field_trial::FindFullName(const std::string& trial).
|
||||
//
|
||||
// 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("WebRTCExperimentMethod2") == "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 negotiation between involved parties (e.g. SDP).
|
||||
//
|
||||
// TODO(andresp): since chrome --force-fieldtrials does not marks the trial
|
||||
// as active it does not get propagated to the 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);
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Enabled".
|
||||
// TODO(tommi): Make sure all implementations support this.
|
||||
inline bool IsEnabled(const char* name) {
|
||||
return FindFullName(name).find("Enabled") == 0;
|
||||
}
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Disabled".
|
||||
inline bool IsDisabled(const char* name) {
|
||||
return FindFullName(name).find("Disabled") == 0;
|
||||
}
|
||||
|
||||
// Optionally initialize field trial from a string.
|
||||
// This method can be called at most once before any other call into webrtc.
|
||||
// E.g. before the peer connection factory is constructed.
|
||||
// Note: trials_string must never be destroyed.
|
||||
void InitFieldTrialsFromString(const char* trials_string);
|
||||
|
||||
const char* GetFieldTrialString();
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
// Validates the given field trial string.
|
||||
bool FieldTrialsStringIsValid(const char* trials_string);
|
||||
|
||||
// Merges two field trial strings.
|
||||
//
|
||||
// If a key (trial) exists twice with conflicting values (groups), the value
|
||||
// in 'second' takes precedence.
|
||||
// Shall only be called with valid FieldTrial strings.
|
||||
std::string MergeFieldTrialsStrings(const char* first, const char* second);
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_FILE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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 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;
|
||||
int Rewind() override;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_FILE_WRAPPER_H_
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_LOGGING_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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(NDEBUG)) || 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_INCLUDE_LOGGING_H_
|
@ -8,13 +8,51 @@
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "rtc_base/atomic_ops.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
#if defined(RTC_DISABLE_METRICS)
|
||||
#define RTC_METRICS_ENABLED 0
|
||||
#else
|
||||
#define RTC_METRICS_ENABLED 1
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics_impl {
|
||||
template <typename... Ts>
|
||||
void NoOp(const Ts&...) {}
|
||||
}
|
||||
}
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
#define EXPECT_METRIC_EQ(val1, val2) EXPECT_EQ(val1, val2)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) \
|
||||
EXPECT_EQ_WAIT(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_GT(val1, val2) EXPECT_GT(val1, val2)
|
||||
#define EXPECT_METRIC_LE(val1, val2) EXPECT_LE(val1, val2)
|
||||
#define EXPECT_METRIC_TRUE(conditon) EXPECT_TRUE(conditon)
|
||||
#define EXPECT_METRIC_FALSE(conditon) EXPECT_FALSE(conditon)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) EXPECT_THAT(value, matcher)
|
||||
#else
|
||||
#define EXPECT_METRIC_EQ(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) webrtc::metrics_impl::NoOp(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_GT(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_LE(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_TRUE(condition) webrtc::metrics_impl::NoOp(condition || true)
|
||||
#define EXPECT_METRIC_FALSE(condition) webrtc::metrics_impl::NoOp(condition && false)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) webrtc::metrics_impl::NoOp(value, testing::_)
|
||||
#endif
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
// Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate
|
||||
// statistics.
|
||||
//
|
||||
@ -29,20 +67,21 @@
|
||||
// The macros use the methods HistogramFactoryGetCounts,
|
||||
// HistogramFactoryGetEnumeration and HistogramAdd.
|
||||
//
|
||||
// Therefore, WebRTC clients must either:
|
||||
//
|
||||
// - provide implementations of
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetCounts(
|
||||
// const std::string& name, int sample, int min, int max,
|
||||
// int bucket_count);
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetEnumeration(
|
||||
// const std::string& name, int sample, int boundary);
|
||||
// void webrtc::metrics::HistogramAdd(
|
||||
// Histogram* histogram_pointer, const std::string& name, int sample);
|
||||
//
|
||||
// - or link with the default implementations (i.e.
|
||||
// system_wrappers/system_wrappers.gyp:metrics_default).
|
||||
// By default WebRTC provides implementations of the aforementioned methods
|
||||
// that can be found in system_wrappers/source/metrics.cc. If clients want to
|
||||
// provide a custom version, they will have to:
|
||||
//
|
||||
// 1. Compile WebRTC defining the preprocessor macro
|
||||
// WEBRTC_EXCLUDE_METRICS_DEFAULT (if GN is used this can be achieved
|
||||
// by setting the GN arg rtc_exclude_metrics_default to true).
|
||||
// 2. Provide implementations of:
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetCounts(
|
||||
// const std::string& name, int sample, int min, int max,
|
||||
// int bucket_count);
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetEnumeration(
|
||||
// const std::string& name, int sample, int boundary);
|
||||
// void webrtc::metrics::HistogramAdd(
|
||||
// Histogram* histogram_pointer, const std::string& name, int sample);
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
@ -55,57 +94,270 @@
|
||||
// };
|
||||
//
|
||||
// RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary);
|
||||
|
||||
//
|
||||
// NOTE: It is recommended to do the Chromium review for modifications to
|
||||
// histograms.xml before new metrics are committed to WebRTC.
|
||||
|
||||
// Macros for adding samples to a named histogram.
|
||||
|
||||
// Histogram for counters (exponentially spaced buckets).
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCountsLinear( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
// Slow metrics: pointer to metric is acquired at each call and is not cached.
|
||||
//
|
||||
// NOTE: this is a temporary solution.
|
||||
// The aim is to mimic the behaviour in Chromium's src/base/metrics/histograms.h
|
||||
// However as atomics are not supported in webrtc, this is for now a modified
|
||||
// and temporary solution. Note that the histogram is constructed/found for
|
||||
// each call. Therefore, for now only use this implementation for metrics
|
||||
// that do not need to be updated frequently.
|
||||
// TODO(asapersson): Change implementation when atomics are supported.
|
||||
// Also consider changing string to const char* when switching to atomics.
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50)
|
||||
|
||||
// Histogram for counters.
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 100, 50)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 200, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 200, 50)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 500, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 1000, 50)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 1000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 10000, 50)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 10000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 100000, 50)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
name, min, max, bucket_count))
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
// Histogram for percentage.
|
||||
// Histogram for percentage (evenly spaced buckets).
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 101)
|
||||
|
||||
// Histogram for booleans.
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
//
|
||||
// TODO(qingsi): Refactor the default implementation given by RtcHistogram,
|
||||
// which is already sparse, and remove the boundary argument from the macro.
|
||||
#define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
|
||||
name, sample, \
|
||||
webrtc::metrics::SparseHistogramFactoryGetEnumeration(name, boundary))
|
||||
|
||||
// Histogram for percentage (evenly spaced buckets).
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
|
||||
|
||||
// Histogram for enumerators.
|
||||
// Histogram for booleans.
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
|
||||
name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
|
||||
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
do { \
|
||||
webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, constant_name, sample); \
|
||||
// The name of the histogram should not vary.
|
||||
// TODO(asapersson): Consider changing string to const char*.
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
do { \
|
||||
static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \
|
||||
webrtc::metrics::Histogram* histogram_pointer = \
|
||||
rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \
|
||||
if (!histogram_pointer) { \
|
||||
histogram_pointer = factory_get_invocation; \
|
||||
webrtc::metrics::Histogram* prev_pointer = \
|
||||
rtc::AtomicOps::CompareAndSwapPtr( \
|
||||
&atomic_histogram_pointer, \
|
||||
static_cast<webrtc::metrics::Histogram*>(nullptr), \
|
||||
histogram_pointer); \
|
||||
RTC_DCHECK(prev_pointer == nullptr || \
|
||||
prev_pointer == histogram_pointer); \
|
||||
} \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// The histogram is constructed/found for each call.
|
||||
// May be used for histograms with infrequent updates.`
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
|
||||
do { \
|
||||
webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Helper macros.
|
||||
// Macros for calling a histogram with varying name (e.g. when using a metric
|
||||
// in different modes such as real-time vs screenshare). Fast, because pointer
|
||||
// is cached. |index| should be different for different names. Allowed |index|
|
||||
// values are 0, 1, and 2.
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, boundary))
|
||||
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_PERCENTAGE(name, sample))
|
||||
|
||||
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
|
||||
do { \
|
||||
switch (index) { \
|
||||
case 0: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
case 1: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
case 2: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
default: \
|
||||
RTC_NOTREACHED(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This section defines no-op alternatives to the metrics macros when
|
||||
// RTC_METRICS_ENABLED is defined.
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
webrtc::metrics_impl::NoOp(constant_name, sample, factory_get_invocation)
|
||||
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, factory_get_invocation)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, macro_invocation)
|
||||
|
||||
#endif // RTC_METRICS_ENABLED
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
@ -119,21 +371,68 @@ class Histogram;
|
||||
// histogram).
|
||||
|
||||
// Get histogram for counters.
|
||||
Histogram* HistogramFactoryGetCounts(
|
||||
const std::string& name, int min, int max, int bucket_count);
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for counters with linear bucket spacing.
|
||||
Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for enumerators.
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
Histogram* HistogramFactoryGetEnumeration(
|
||||
const std::string& name, int boundary);
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary);
|
||||
|
||||
// Get sparse histogram for enumerators.
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary);
|
||||
|
||||
// Function for adding a |sample| to a histogram.
|
||||
// |name| can be used to verify that it matches the histogram name.
|
||||
void HistogramAdd(
|
||||
Histogram* histogram_pointer, const std::string& name, int sample);
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample);
|
||||
|
||||
struct SampleInfo {
|
||||
SampleInfo(const std::string& name, int min, int max, size_t bucket_count);
|
||||
~SampleInfo();
|
||||
|
||||
const std::string name;
|
||||
const int min;
|
||||
const int max;
|
||||
const size_t bucket_count;
|
||||
std::map<int, int> samples; // <value, # of events>
|
||||
};
|
||||
|
||||
// Enables collection of samples.
|
||||
// This method should be called before any other call into webrtc.
|
||||
void Enable();
|
||||
|
||||
// Gets histograms and clears all samples.
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms);
|
||||
|
||||
// Functions below are mainly for testing.
|
||||
|
||||
// Clears all samples.
|
||||
void Reset();
|
||||
|
||||
// Returns the number of times the |sample| has been added to the histogram.
|
||||
int NumEvents(const std::string& name, int sample);
|
||||
|
||||
// Returns the total number of added samples to the histogram.
|
||||
int NumSamples(const std::string& name);
|
||||
|
||||
// Returns the minimum sample value (or -1 if the histogram has no samples).
|
||||
int MinSample(const std::string& name);
|
||||
|
||||
// Returns a map with keys the samples with at least one event and values the
|
||||
// number of events for that sample.
|
||||
std::map<int, int> Samples(const std::string& name);
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_RW_LOCK_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RW_LOCK_WRAPPER_H_
|
||||
|
||||
#include "webrtc/base/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_INCLUDE_RW_LOCK_WRAPPER_H_
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_SCOPED_VECTOR_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SCOPED_VECTOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/system_wrappers/include/stl_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// ScopedVector wraps a vector deleting the elements from its
|
||||
// destructor.
|
||||
template <class T>
|
||||
class ScopedVector {
|
||||
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(); }
|
||||
|
||||
// Move construction and assignment.
|
||||
ScopedVector(ScopedVector&& other) {
|
||||
*this = static_cast<ScopedVector&&>(other);
|
||||
}
|
||||
ScopedVector& operator=(ScopedVector&& other) {
|
||||
std::swap(v_, other.v_); // The arguments are std::vectors, so std::swap
|
||||
// is the one that we want.
|
||||
other.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Deleted copy constructor and copy assignment, to make the type move-only.
|
||||
ScopedVector(const ScopedVector& other) = delete;
|
||||
ScopedVector& operator=(const ScopedVector& other) = delete;
|
||||
|
||||
// Get an rvalue reference. (sv.Pass() does the same thing as std::move(sv).)
|
||||
ScopedVector&& Pass() { return static_cast<ScopedVector&&>(*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() {
|
||||
RTC_DCHECK(!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_INCLUDE_SCOPED_VECTOR_H_
|
@ -9,8 +9,8 @@
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -21,4 +21,4 @@ void SleepMs(int msecs);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_STATIC_INSTANCE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_STATIC_INSTANCE_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/include/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_INCLUDE_STATIC_INSTANCE_H_
|
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_STL_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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_INCLUDE_STL_UTIL_H_
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_THREAD_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_THREAD_WRAPPER_H_
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// 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)(void*);
|
||||
|
||||
enum ThreadPriority {
|
||||
#ifdef WEBRTC_WIN
|
||||
kLowPriority = THREAD_PRIORITY_BELOW_NORMAL,
|
||||
kNormalPriority = THREAD_PRIORITY_NORMAL,
|
||||
kHighPriority = THREAD_PRIORITY_ABOVE_NORMAL,
|
||||
kHighestPriority = THREAD_PRIORITY_HIGHEST,
|
||||
kRealtimePriority = THREAD_PRIORITY_TIME_CRITICAL
|
||||
#else
|
||||
kLowPriority = 1,
|
||||
kNormalPriority = 2,
|
||||
kHighPriority = 3,
|
||||
kHighestPriority = 4,
|
||||
kRealtimePriority = 5
|
||||
#endif
|
||||
};
|
||||
|
||||
// Represents a simple worker thread. The implementation must be assumed
|
||||
// to be single threaded, meaning that all methods of the class, must be
|
||||
// called from the same thread, including instantiation.
|
||||
// TODO(tommi): There's no need for this to be a virtual interface since there's
|
||||
// only ever a single implementation of it.
|
||||
class ThreadWrapper {
|
||||
public:
|
||||
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 rtc::scoped_ptr<ThreadWrapper> CreateThread(ThreadRunFunction func,
|
||||
void* obj, const char* thread_name);
|
||||
|
||||
// Get the current thread's thread ID.
|
||||
// NOTE: This is a static method. It returns the id of the calling thread,
|
||||
// *not* the id of the worker thread that a ThreadWrapper instance represents.
|
||||
// TODO(tommi): Move outside of the ThreadWrapper class to avoid confusion.
|
||||
static uint32_t GetThreadId();
|
||||
|
||||
// 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.
|
||||
virtual bool Start() = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// Set the priority of the worker thread. Must be called when thread
|
||||
// is running.
|
||||
virtual bool SetPriority(ThreadPriority priority) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_THREAD_WRAPPER_H_
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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_INCLUDE_TRACE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_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(int filter);
|
||||
|
||||
// Returns what type of messages are written to the trace file.
|
||||
static int 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 volatile int level_filter_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_TRACE_H_
|
@ -1,47 +1,18 @@
|
||||
system_wrappers_sources = [
|
||||
'source/aligned_malloc.cc',
|
||||
'source/cpu_features.cc',
|
||||
'source/event.cc',
|
||||
'source/file_impl.cc',
|
||||
'source/critical_section.cc',
|
||||
'source/logging.cc',
|
||||
'source/metrics_default.cc',
|
||||
'source/rw_lock.cc',
|
||||
'source/field_trial.cc',
|
||||
'source/metrics.cc',
|
||||
'source/sleep.cc',
|
||||
'source/thread.cc',
|
||||
'source/trace_impl.cc',
|
||||
]
|
||||
|
||||
if have_posix
|
||||
system_wrappers_sources += [
|
||||
'source/critical_section_posix.cc',
|
||||
'source/event_timer_posix.cc',
|
||||
'source/rw_lock_posix.cc',
|
||||
'source/thread_posix.cc',
|
||||
'source/trace_posix.cc',
|
||||
]
|
||||
endif
|
||||
|
||||
if have_win
|
||||
system_wrappers_sources += [
|
||||
'source/critical_section_win.cc',
|
||||
'source/condition_variable.cc',
|
||||
'source/condition_variable_event_win.cc',
|
||||
'source/condition_variable_native_win.cc',
|
||||
'source/event_timer_win.cc',
|
||||
'source/rw_lock_win.cc',
|
||||
'source/rw_lock_generic.cc',
|
||||
'source/thread_win.cc',
|
||||
'source/trace_win.cc',
|
||||
]
|
||||
endif
|
||||
|
||||
system_headers = [
|
||||
'include/trace.h',
|
||||
'include/cpu_features_wrapper.h',
|
||||
'include/metrics.h',
|
||||
'include/sleep.h',
|
||||
]
|
||||
|
||||
install_headers(system_headers,
|
||||
subdir: 'webrtc_audio_processing/webrtc/system_wrappers/include'
|
||||
subdir: 'webrtc_audio_processing/system_wrappers/include'
|
||||
)
|
||||
|
||||
libsystem_wrappers = static_library('system_wrappers',
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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/include/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
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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/include/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
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
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
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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/include/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_
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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/include/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
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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/include/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_
|
@ -10,13 +10,15 @@
|
||||
|
||||
// Parts of this file derived from Chromium's base/cpu.cc.
|
||||
|
||||
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
#include "system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
namespace webrtc {
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
@ -25,23 +27,40 @@ int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
// xgetbv returns the value of an Intel Extended Control Register (XCR).
|
||||
// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
|
||||
static uint64_t xgetbv(uint32_t xcr) {
|
||||
#if defined(_MSC_VER)
|
||||
return _xgetbv(xcr);
|
||||
#else
|
||||
uint32_t eax, edx;
|
||||
|
||||
__asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
|
||||
return (static_cast<uint64_t>(edx) << 32) | eax;
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
|
||||
#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));
|
||||
"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));
|
||||
__asm__ volatile("cpuid\n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type), "c"(0));
|
||||
}
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
@ -49,7 +68,7 @@ static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
// Actual feature detection for x86.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
if (feature == kSSE2) {
|
||||
@ -58,15 +77,39 @@ static int GetCPUInfo(CPUFeature feature) {
|
||||
if (feature == kSSE3) {
|
||||
return 0 != (cpu_info[2] & 0x00000001);
|
||||
}
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
if (feature == kAVX2 &&
|
||||
!webrtc::field_trial::IsEnabled("WebRTC-Avx2SupportKillSwitch")) {
|
||||
int cpu_info7[4];
|
||||
__cpuid(cpu_info7, 0);
|
||||
int num_ids = cpu_info7[0];
|
||||
if (num_ids < 7) {
|
||||
return 0;
|
||||
}
|
||||
// Interpret CPU feature information.
|
||||
__cpuid(cpu_info7, 7);
|
||||
|
||||
// AVX instructions can be used when
|
||||
// a) AVX are supported by the CPU,
|
||||
// b) XSAVE is supported by the CPU,
|
||||
// c) XSAVE is enabled by the kernel.
|
||||
// See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
|
||||
// AVX2 support needs (avx_support && (cpu_info7[1] & 0x00000020) != 0;).
|
||||
return (cpu_info[2] & 0x10000000) != 0 &&
|
||||
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
|
||||
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
|
||||
(xgetbv(0) & 0x00000006) == 6 /* XSAVE enabled by kernel */ &&
|
||||
(cpu_info7[1] & 0x00000020) != 0;
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Default to straight C for other platforms.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfo = GetCPUInfo;
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM = GetCPUInfoNoASM;
|
||||
} // namespace webrtc
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
// 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
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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/include/critical_section_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionPosix : public CriticalSectionWrapper {
|
||||
public:
|
||||
CriticalSectionPosix();
|
||||
|
||||
~CriticalSectionPosix() override;
|
||||
|
||||
void Enter() override;
|
||||
void Leave() override;
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
friend class ConditionVariablePosix;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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/include/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_
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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/include/event_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_win.h"
|
||||
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_posix.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_posix.h"
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventWrapperImpl : public EventWrapper {
|
||||
public:
|
||||
EventWrapperImpl() : event_(false, false) {}
|
||||
~EventWrapperImpl() override {}
|
||||
|
||||
bool Set() override {
|
||||
event_.Set();
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper Wait(unsigned long max_time) override {
|
||||
int to_wait = max_time == WEBRTC_EVENT_INFINITE ?
|
||||
rtc::Event::kForever : static_cast<int>(max_time);
|
||||
return event_.Wait(to_wait) ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::Event event_;
|
||||
};
|
||||
|
||||
// static
|
||||
EventWrapper* EventWrapper::Create() {
|
||||
return new EventWrapperImpl();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,231 +0,0 @@
|
||||
/*
|
||||
* 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_timer_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
EventTimerWrapper* EventTimerWrapper::Create() {
|
||||
return new EventTimerPosix();
|
||||
}
|
||||
|
||||
const long int E6 = 1000000;
|
||||
const long int E9 = 1000 * E6;
|
||||
|
||||
EventTimerPosix::EventTimerPosix()
|
||||
: event_set_(false),
|
||||
timer_thread_(nullptr),
|
||||
created_at_(),
|
||||
periodic_(false),
|
||||
time_(0),
|
||||
count_(0) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mutex_, &attr);
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
pthread_cond_init(&cond_, 0);
|
||||
#else
|
||||
pthread_condattr_t cond_attr;
|
||||
pthread_condattr_init(&cond_attr);
|
||||
pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
|
||||
pthread_cond_init(&cond_, &cond_attr);
|
||||
pthread_condattr_destroy(&cond_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
EventTimerPosix::~EventTimerPosix() {
|
||||
StopTimer();
|
||||
pthread_cond_destroy(&cond_);
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
// TODO(pbos): Make this void.
|
||||
bool EventTimerPosix::Set() {
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
event_set_ = true;
|
||||
pthread_cond_signal(&cond_);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerPosix::Wait(unsigned long timeout) {
|
||||
int ret_val = 0;
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
|
||||
if (!event_set_) {
|
||||
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;
|
||||
}
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
|
||||
} else {
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_wait(&cond_, &mutex_);
|
||||
}
|
||||
}
|
||||
|
||||
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
|
||||
|
||||
// Reset and signal if set, regardless of why the thread woke up.
|
||||
if (event_set_) {
|
||||
ret_val = 0;
|
||||
event_set_ = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return ret_val == 0 ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerPosix::Wait(timespec* end_at) {
|
||||
int ret_val = 0;
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, end_at);
|
||||
|
||||
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
|
||||
|
||||
// Reset and signal if set, regardless of why the thread woke up.
|
||||
if (event_set_) {
|
||||
ret_val = 0;
|
||||
event_set_ = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return ret_val == 0 ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::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_.reset(new EventTimerPosix());
|
||||
const char* thread_name = "WebRtc_event_timer_thread";
|
||||
timer_thread_ = ThreadWrapper::CreateThread(Run, this, thread_name);
|
||||
periodic_ = periodic;
|
||||
time_ = time;
|
||||
bool started = timer_thread_->Start();
|
||||
timer_thread_->SetPriority(kRealtimePriority);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::Run(void* obj) {
|
||||
return static_cast<EventTimerPosix*>(obj)->Process();
|
||||
}
|
||||
|
||||
bool EventTimerPosix::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_);
|
||||
if (timer_event_->Wait(&end_at) == kEventSignaled)
|
||||
return true;
|
||||
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (periodic_ || count_ == 1)
|
||||
Set();
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::StopTimer() {
|
||||
if (timer_event_) {
|
||||
timer_event_->Set();
|
||||
}
|
||||
if (timer_thread_) {
|
||||
if (!timer_thread_->Stop()) {
|
||||
return false;
|
||||
}
|
||||
timer_thread_.reset();
|
||||
}
|
||||
timer_event_.reset();
|
||||
|
||||
// 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
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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/include/event_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum State {
|
||||
kUp = 1,
|
||||
kDown = 2
|
||||
};
|
||||
|
||||
class EventTimerPosix : public EventTimerWrapper {
|
||||
public:
|
||||
EventTimerPosix();
|
||||
~EventTimerPosix() override;
|
||||
|
||||
EventTypeWrapper Wait(unsigned long max_time) override;
|
||||
bool Set() override;
|
||||
|
||||
bool StartTimer(bool periodic, unsigned long time) override;
|
||||
bool StopTimer() override;
|
||||
|
||||
private:
|
||||
static bool Run(void* obj);
|
||||
bool Process();
|
||||
EventTypeWrapper Wait(timespec* end_at);
|
||||
|
||||
private:
|
||||
pthread_cond_t cond_;
|
||||
pthread_mutex_t mutex_;
|
||||
bool event_set_;
|
||||
|
||||
rtc::scoped_ptr<ThreadWrapper> timer_thread_;
|
||||
rtc::scoped_ptr<EventTimerPosix> timer_event_;
|
||||
timespec created_at_;
|
||||
|
||||
bool periodic_;
|
||||
unsigned long time_; // In ms
|
||||
unsigned long count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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_timer_win.h"
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
EventTimerWrapper* EventTimerWrapper::Create() {
|
||||
return new EventTimerWin();
|
||||
}
|
||||
|
||||
EventTimerWin::EventTimerWin()
|
||||
: event_(::CreateEvent(NULL, // security attributes
|
||||
FALSE, // manual reset
|
||||
FALSE, // initial state
|
||||
NULL)), // name of event
|
||||
timerID_(NULL) {
|
||||
}
|
||||
|
||||
EventTimerWin::~EventTimerWin() {
|
||||
StopTimer();
|
||||
CloseHandle(event_);
|
||||
}
|
||||
|
||||
bool EventTimerWin::Set() {
|
||||
// Note: setting an event that is already set has no effect.
|
||||
return SetEvent(event_) == 1;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerWin::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 EventTimerWin::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 EventTimerWin::StopTimer() {
|
||||
if (timerID_ != NULL) {
|
||||
timeKillEvent(timerID_);
|
||||
timerID_ = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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/include/event_wrapper.h"
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventTimerWin : public EventTimerWrapper {
|
||||
public:
|
||||
EventTimerWin();
|
||||
virtual ~EventTimerWin();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time);
|
||||
virtual bool Set();
|
||||
|
||||
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_
|
155
webrtc/system_wrappers/source/field_trial.cc
Normal file
155
webrtc/system_wrappers/source/field_trial.cc
Normal file
@ -0,0 +1,155 @@
|
||||
// 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 "system_wrappers/include/field_trial.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
|
||||
// Simple field trial implementation, which allows client to
|
||||
// specify desired flags in InitFieldTrialsFromString.
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
static const char* trials_init_string = NULL;
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
namespace {
|
||||
constexpr char kPersistentStringSeparator = '/';
|
||||
// Validates the given field trial string.
|
||||
// E.g.:
|
||||
// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
|
||||
// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial
|
||||
// and to group "Enabled100kbps" on WebRTCExperimentBar.
|
||||
//
|
||||
// E.g. invalid config:
|
||||
// "WebRTC-experiment1/Enabled" (note missing / separator at the end).
|
||||
bool FieldTrialsStringIsValidInternal(const absl::string_view trials) {
|
||||
if (trials.empty())
|
||||
return true;
|
||||
|
||||
size_t next_item = 0;
|
||||
std::map<absl::string_view, absl::string_view> field_trials;
|
||||
while (next_item < trials.length()) {
|
||||
size_t name_end = trials.find(kPersistentStringSeparator, next_item);
|
||||
if (name_end == trials.npos || next_item == name_end)
|
||||
return false;
|
||||
size_t group_name_end =
|
||||
trials.find(kPersistentStringSeparator, name_end + 1);
|
||||
if (group_name_end == trials.npos || name_end + 1 == group_name_end)
|
||||
return false;
|
||||
absl::string_view name = trials.substr(next_item, name_end - next_item);
|
||||
absl::string_view group_name =
|
||||
trials.substr(name_end + 1, group_name_end - name_end - 1);
|
||||
|
||||
next_item = group_name_end + 1;
|
||||
|
||||
// Fail if duplicate with different group name.
|
||||
if (field_trials.find(name) != field_trials.end() &&
|
||||
field_trials.find(name)->second != group_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
field_trials[name] = group_name;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool FieldTrialsStringIsValid(const char* trials_string) {
|
||||
return FieldTrialsStringIsValidInternal(trials_string);
|
||||
}
|
||||
|
||||
void InsertOrReplaceFieldTrialStringsInMap(
|
||||
std::map<std::string, std::string>* fieldtrial_map,
|
||||
const absl::string_view trials_string) {
|
||||
if (FieldTrialsStringIsValidInternal(trials_string)) {
|
||||
std::vector<std::string> tokens;
|
||||
rtc::split(std::string(trials_string), '/', &tokens);
|
||||
// Skip last token which is empty due to trailing '/'.
|
||||
for (size_t idx = 0; idx < tokens.size() - 1; idx += 2) {
|
||||
(*fieldtrial_map)[tokens[idx]] = tokens[idx + 1];
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK(false) << "Invalid field trials string:" << trials_string;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MergeFieldTrialsStrings(const char* first, const char* second) {
|
||||
std::map<std::string, std::string> fieldtrial_map;
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, first);
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, second);
|
||||
|
||||
// Merge into fieldtrial string.
|
||||
std::string merged = "";
|
||||
for (auto const& fieldtrial : fieldtrial_map) {
|
||||
merged += fieldtrial.first + '/' + fieldtrial.second + '/';
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
std::string FindFullName(const std::string& name) {
|
||||
if (trials_init_string == NULL)
|
||||
return std::string();
|
||||
|
||||
std::string trials_string(trials_init_string);
|
||||
if (trials_string.empty())
|
||||
return std::string();
|
||||
|
||||
size_t next_item = 0;
|
||||
while (next_item < trials_string.length()) {
|
||||
// Find next name/value pair in field trial configuration string.
|
||||
size_t field_name_end =
|
||||
trials_string.find(kPersistentStringSeparator, next_item);
|
||||
if (field_name_end == trials_string.npos || field_name_end == next_item)
|
||||
break;
|
||||
size_t field_value_end =
|
||||
trials_string.find(kPersistentStringSeparator, field_name_end + 1);
|
||||
if (field_value_end == trials_string.npos ||
|
||||
field_value_end == field_name_end + 1)
|
||||
break;
|
||||
std::string field_name(trials_string, next_item,
|
||||
field_name_end - next_item);
|
||||
std::string field_value(trials_string, field_name_end + 1,
|
||||
field_value_end - field_name_end - 1);
|
||||
next_item = field_value_end + 1;
|
||||
|
||||
if (name == field_name)
|
||||
return field_value;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
|
||||
// Optionally initialize field trial from a string.
|
||||
void InitFieldTrialsFromString(const char* trials_string) {
|
||||
RTC_LOG(LS_INFO) << "Setting field trial string:" << trials_string;
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
if (trials_string) {
|
||||
RTC_DCHECK(FieldTrialsStringIsValidInternal(trials_string))
|
||||
<< "Invalid field trials string:" << trials_string;
|
||||
};
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
trials_init_string = trials_string;
|
||||
}
|
||||
|
||||
const char* GetFieldTrialString() {
|
||||
return trials_init_string;
|
||||
}
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* 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/base/checks.h"
|
||||
#include "webrtc/system_wrappers/include/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, size_t length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (id_ == NULL)
|
||||
return -1;
|
||||
|
||||
size_t bytes_read = fread(buf, 1, length, id_);
|
||||
if (bytes_read != length && !looping_) {
|
||||
CloseFileImpl();
|
||||
}
|
||||
return static_cast<int>(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, size_t length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (buf == NULL)
|
||||
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;
|
||||
}
|
||||
|
||||
int FileWrapper::Rewind() {
|
||||
RTC_DCHECK(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWrapper;
|
||||
|
||||
class FileWrapperImpl : public FileWrapper {
|
||||
public:
|
||||
FileWrapperImpl();
|
||||
~FileWrapperImpl() override;
|
||||
|
||||
int FileName(char* file_name_utf8, size_t size) const override;
|
||||
|
||||
bool Open() const override;
|
||||
|
||||
int OpenFile(const char* file_name_utf8,
|
||||
bool read_only,
|
||||
bool loop = false,
|
||||
bool text = false) override;
|
||||
|
||||
int OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop = false) override;
|
||||
|
||||
int CloseFile() override;
|
||||
int SetMaxFileSize(size_t bytes) override;
|
||||
int Flush() override;
|
||||
|
||||
int Read(void* buf, size_t length) override;
|
||||
bool Write(const void* buf, size_t length) override;
|
||||
int WriteText(const char* format, ...) override;
|
||||
int Rewind() override;
|
||||
|
||||
private:
|
||||
int CloseFileImpl();
|
||||
int FlushImpl();
|
||||
|
||||
rtc::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_
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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/include/logging.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/system_wrappers/include/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;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the filename portion of the string (that following the last slash).
|
||||
const char* FilenameFromPath(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_ << "(" << FilenameFromPath(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, "%s", str.c_str());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
328
webrtc/system_wrappers/source/metrics.cc
Normal file
328
webrtc/system_wrappers/source/metrics.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.
|
||||
//
|
||||
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
// Default implementation of histogram methods for WebRTC clients that do not
|
||||
// want to provide their own implementation.
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
class Histogram;
|
||||
|
||||
namespace {
|
||||
// Limit for the maximum number of sample values that can be stored.
|
||||
// TODO(asapersson): Consider using bucket count (and set up
|
||||
// linearly/exponentially spaced buckets) if samples are logged more frequently.
|
||||
const int kMaxSampleMapSize = 300;
|
||||
|
||||
class RtcHistogram {
|
||||
public:
|
||||
RtcHistogram(const std::string& name, int min, int max, int bucket_count)
|
||||
: min_(min), max_(max), info_(name, min, max, bucket_count) {
|
||||
RTC_DCHECK_GT(bucket_count, 0);
|
||||
}
|
||||
|
||||
void Add(int sample) {
|
||||
sample = std::min(sample, max_);
|
||||
sample = std::max(sample, min_ - 1); // Underflow bucket.
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.size() == kMaxSampleMapSize &&
|
||||
info_.samples.find(sample) == info_.samples.end()) {
|
||||
return;
|
||||
}
|
||||
++info_.samples[sample];
|
||||
}
|
||||
|
||||
// Returns a copy (or nullptr if there are no samples) and clears samples.
|
||||
std::unique_ptr<SampleInfo> GetAndReset() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.empty())
|
||||
return nullptr;
|
||||
|
||||
SampleInfo* copy =
|
||||
new SampleInfo(info_.name, info_.min, info_.max, info_.bucket_count);
|
||||
|
||||
std::swap(info_.samples, copy->samples);
|
||||
|
||||
return std::unique_ptr<SampleInfo>(copy);
|
||||
}
|
||||
|
||||
const std::string& name() const { return info_.name; }
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
info_.samples.clear();
|
||||
}
|
||||
|
||||
int NumEvents(int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto it = info_.samples.find(sample);
|
||||
return (it == info_.samples.end()) ? 0 : it->second;
|
||||
}
|
||||
|
||||
int NumSamples() const {
|
||||
int num_samples = 0;
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& sample : info_.samples) {
|
||||
num_samples += sample.second;
|
||||
}
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
int MinSample() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return (info_.samples.empty()) ? -1 : info_.samples.begin()->first;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return info_.samples;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
const int min_;
|
||||
const int max_;
|
||||
SampleInfo info_ RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogram);
|
||||
};
|
||||
|
||||
class RtcHistogramMap {
|
||||
public:
|
||||
RtcHistogramMap() {}
|
||||
~RtcHistogramMap() {}
|
||||
|
||||
Histogram* GetCountsHistogram(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, min, max, bucket_count);
|
||||
map_[name].reset(hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
Histogram* GetEnumerationHistogram(const std::string& name, int boundary) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, 1, boundary, boundary + 1);
|
||||
map_[name].reset(hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_) {
|
||||
std::unique_ptr<SampleInfo> info = kv.second->GetAndReset();
|
||||
if (info)
|
||||
histograms->insert(std::make_pair(kv.first, std::move(info)));
|
||||
}
|
||||
}
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_)
|
||||
kv.second->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumEvents(sample);
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumSamples();
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? -1 : it->second->MinSample();
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? std::map<int, int>() : it->second->Samples();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
std::map<std::string, std::unique_ptr<RtcHistogram>> map_
|
||||
RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogramMap);
|
||||
};
|
||||
|
||||
// RtcHistogramMap is allocated upon call to Enable().
|
||||
// The histogram getter functions, which return pointer values to the histograms
|
||||
// in the map, are cached in WebRTC. Therefore, this memory is not freed by the
|
||||
// application (the memory will be reclaimed by the OS).
|
||||
static RtcHistogramMap* volatile g_rtc_histogram_map = nullptr;
|
||||
|
||||
void CreateMap() {
|
||||
RtcHistogramMap* map = rtc::AtomicOps::AcquireLoadPtr(&g_rtc_histogram_map);
|
||||
if (map == nullptr) {
|
||||
RtcHistogramMap* new_map = new RtcHistogramMap();
|
||||
RtcHistogramMap* old_map = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
&g_rtc_histogram_map, static_cast<RtcHistogramMap*>(nullptr), new_map);
|
||||
if (old_map != nullptr)
|
||||
delete new_map;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first time we start using histograms. Used to make sure Enable() is
|
||||
// not called thereafter.
|
||||
#if RTC_DCHECK_IS_ON
|
||||
static volatile int g_rtc_histogram_called = 0;
|
||||
#endif
|
||||
|
||||
// Gets the map (or nullptr).
|
||||
RtcHistogramMap* GetMap() {
|
||||
#if RTC_DCHECK_IS_ON
|
||||
rtc::AtomicOps::ReleaseStore(&g_rtc_histogram_called, 1);
|
||||
#endif
|
||||
return g_rtc_histogram_map;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
// Implementation of histogram methods in
|
||||
// webrtc/system_wrappers/interface/metrics.h.
|
||||
|
||||
// Histogram with exponentially spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
// TODO(asapersson): Alternative implementation will be needed if this
|
||||
// histogram type should be truly exponential.
|
||||
return HistogramFactoryGetCountsLinear(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetCountsHistogram(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetEnumerationHistogram(name, boundary);
|
||||
}
|
||||
|
||||
// Our default implementation reuses the non-sparse histogram.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) {
|
||||
return HistogramFactoryGetEnumeration(name, boundary);
|
||||
}
|
||||
|
||||
// Fast path. Adds |sample| to cached |histogram_pointer|.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample) {
|
||||
RtcHistogram* ptr = reinterpret_cast<RtcHistogram*>(histogram_pointer);
|
||||
ptr->Add(sample);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
|
||||
SampleInfo::SampleInfo(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
size_t bucket_count)
|
||||
: name(name), min(min), max(max), bucket_count(bucket_count) {}
|
||||
|
||||
SampleInfo::~SampleInfo() {}
|
||||
|
||||
// Implementation of global functions in metrics.h.
|
||||
void Enable() {
|
||||
RTC_DCHECK(g_rtc_histogram_map == nullptr);
|
||||
#if RTC_DCHECK_IS_ON
|
||||
RTC_DCHECK_EQ(0, rtc::AtomicOps::AcquireLoad(&g_rtc_histogram_called));
|
||||
#endif
|
||||
CreateMap();
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
histograms->clear();
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->GetAndReset(histograms);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumEvents(name, sample) : 0;
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumSamples(name) : 0;
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->MinSample(name) : -1;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->Samples(name) : std::map<int, int>();
|
||||
}
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
@ -1,29 +0,0 @@
|
||||
// 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/include/metrics.h"
|
||||
|
||||
// Default implementation of histogram methods for WebRTC clients that do not
|
||||
// want to provide their own implementation.
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name, int min, int max,
|
||||
int bucket_count) { return NULL; }
|
||||
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) { return NULL; }
|
||||
|
||||
void HistogramAdd(
|
||||
Histogram* histogram_pointer, const std::string& name, int sample) {}
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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/include/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
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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/include/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/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
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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/include/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
class RWLockGeneric : public RWLockWrapper {
|
||||
public:
|
||||
RWLockGeneric();
|
||||
~RWLockGeneric() override;
|
||||
|
||||
void AcquireLockExclusive() override;
|
||||
void ReleaseLockExclusive() override;
|
||||
|
||||
void AcquireLockShared() override;
|
||||
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_
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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/include/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockPosix : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockPosix* Create();
|
||||
~RWLockPosix() override;
|
||||
|
||||
void AcquireLockExclusive() override;
|
||||
void ReleaseLockExclusive() override;
|
||||
|
||||
void AcquireLockShared() override;
|
||||
void ReleaseLockShared() override;
|
||||
|
||||
private:
|
||||
RWLockPosix();
|
||||
bool Init();
|
||||
|
||||
pthread_rwlock_t lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* 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/include/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
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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/include/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_
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "system_wrappers/include/sleep.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
// For Sleep()
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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/include/thread_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "webrtc/system_wrappers/source/thread_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/thread_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if defined(_WIN32)
|
||||
typedef ThreadWindows ThreadType;
|
||||
#else
|
||||
typedef ThreadPosix ThreadType;
|
||||
#endif
|
||||
|
||||
rtc::scoped_ptr<ThreadWrapper> ThreadWrapper::CreateThread(
|
||||
ThreadRunFunction func, void* obj, const char* thread_name) {
|
||||
return rtc::scoped_ptr<ThreadWrapper>(
|
||||
new ThreadType(func, obj, thread_name)).Pass();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* 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/thread_posix.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef WEBRTC_LINUX
|
||||
#include <linux/unistd.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
struct ThreadAttributes {
|
||||
ThreadAttributes() { pthread_attr_init(&attr); }
|
||||
~ThreadAttributes() { pthread_attr_destroy(&attr); }
|
||||
pthread_attr_t* operator&() { return &attr; }
|
||||
pthread_attr_t attr;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
|
||||
int max_prio) {
|
||||
RTC_DCHECK(max_prio - min_prio > 2);
|
||||
const int top_prio = max_prio - 1;
|
||||
const int low_prio = min_prio + 1;
|
||||
|
||||
switch (priority) {
|
||||
case kLowPriority:
|
||||
return low_prio;
|
||||
case kNormalPriority:
|
||||
// The -1 ensures that the kHighPriority is always greater or equal to
|
||||
// kNormalPriority.
|
||||
return (low_prio + top_prio - 1) / 2;
|
||||
case kHighPriority:
|
||||
return std::max(top_prio - 2, low_prio);
|
||||
case kHighestPriority:
|
||||
return std::max(top_prio - 1, low_prio);
|
||||
case kRealtimePriority:
|
||||
return top_prio;
|
||||
}
|
||||
RTC_DCHECK(false);
|
||||
return low_prio;
|
||||
}
|
||||
|
||||
// static
|
||||
void* ThreadPosix::StartThread(void* param) {
|
||||
static_cast<ThreadPosix*>(param)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadPosix::ThreadPosix(ThreadRunFunction func, void* obj,
|
||||
const char* thread_name)
|
||||
: run_function_(func),
|
||||
obj_(obj),
|
||||
stop_event_(false, false),
|
||||
name_(thread_name ? thread_name : "webrtc"),
|
||||
thread_(0) {
|
||||
RTC_DCHECK(name_.length() < 64);
|
||||
}
|
||||
|
||||
uint32_t ThreadWrapper::GetThreadId() {
|
||||
return rtc::CurrentThreadId();
|
||||
}
|
||||
|
||||
ThreadPosix::~ThreadPosix() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
// TODO(pbos): Make Start void, calling code really doesn't support failures
|
||||
// here.
|
||||
bool ThreadPosix::Start() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_) << "Thread already started?";
|
||||
|
||||
ThreadAttributes attr;
|
||||
// Set the stack stack size to 1M.
|
||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||
RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadPosix::Stop() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!thread_)
|
||||
return true;
|
||||
|
||||
stop_event_.Set();
|
||||
RTC_CHECK_EQ(0, pthread_join(thread_, nullptr));
|
||||
thread_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadPosix::SetPriority(ThreadPriority priority) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!thread_)
|
||||
return false;
|
||||
#if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
|
||||
// TODO(tommi): Switch to the same mechanism as Chromium uses for
|
||||
// changing thread priorities.
|
||||
return true;
|
||||
#else
|
||||
#ifdef WEBRTC_THREAD_RR
|
||||
const int policy = SCHED_RR;
|
||||
#else
|
||||
const int policy = SCHED_FIFO;
|
||||
#endif
|
||||
const int min_prio = sched_get_priority_min(policy);
|
||||
const int max_prio = sched_get_priority_max(policy);
|
||||
if (min_prio == -1 || max_prio == -1) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
||||
"unable to retreive min or max priority for threads");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (max_prio - min_prio <= 2)
|
||||
return false;
|
||||
|
||||
sched_param param;
|
||||
param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio);
|
||||
if (pthread_setschedparam(thread_, policy, ¶m) != 0) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceError, kTraceUtility, -1, "unable to set thread priority");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
|
||||
}
|
||||
|
||||
void ThreadPosix::Run() {
|
||||
if (!name_.empty()) {
|
||||
// Setting the thread name may fail (harmlessly) if running inside a
|
||||
// sandbox. Ignore failures if they happen.
|
||||
rtc::SetCurrentThreadName(name_.substr(0, 63).c_str());
|
||||
}
|
||||
|
||||
// It's a requirement that for successful thread creation that the run
|
||||
// function be called at least once (see RunFunctionIsCalled unit test),
|
||||
// so to fullfill that requirement, we use a |do| loop and not |while|.
|
||||
do {
|
||||
if (!run_function_(obj_))
|
||||
break;
|
||||
} while (!stop_event_.Wait(0));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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_THREAD_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_POSIX_H_
|
||||
|
||||
#include "webrtc/base/event.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
|
||||
int max_prio);
|
||||
|
||||
class ThreadPosix : public ThreadWrapper {
|
||||
public:
|
||||
ThreadPosix(ThreadRunFunction func, void* obj, const char* thread_name);
|
||||
~ThreadPosix() override;
|
||||
|
||||
// From ThreadWrapper.
|
||||
bool Start() override;
|
||||
bool Stop() override;
|
||||
|
||||
bool SetPriority(ThreadPriority priority) override;
|
||||
|
||||
private:
|
||||
static void* StartThread(void* param);
|
||||
|
||||
void Run();
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
ThreadRunFunction const run_function_;
|
||||
void* const obj_;
|
||||
rtc::Event stop_event_;
|
||||
const std::string name_;
|
||||
|
||||
pthread_t thread_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_POSIX_H_
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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/thread_win.h"
|
||||
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
void CALLBACK RaiseFlag(ULONG_PTR param) {
|
||||
*reinterpret_cast<bool*>(param) = true;
|
||||
}
|
||||
}
|
||||
|
||||
ThreadWindows::ThreadWindows(ThreadRunFunction func, void* obj,
|
||||
const char* thread_name)
|
||||
: run_function_(func),
|
||||
obj_(obj),
|
||||
stop_(false),
|
||||
thread_(NULL),
|
||||
name_(thread_name ? thread_name : "webrtc") {
|
||||
RTC_DCHECK(func);
|
||||
}
|
||||
|
||||
ThreadWindows::~ThreadWindows() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_);
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t ThreadWrapper::GetThreadId() {
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
// static
|
||||
DWORD WINAPI ThreadWindows::StartThread(void* param) {
|
||||
static_cast<ThreadWindows*>(param)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Start() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_);
|
||||
|
||||
stop_ = false;
|
||||
|
||||
// See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
|
||||
// Set the reserved stack stack size to 1M, which is the default on Windows
|
||||
// and Linux.
|
||||
DWORD thread_id;
|
||||
thread_ = ::CreateThread(NULL, 1024 * 1024, &StartThread, this,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id);
|
||||
if (!thread_ ) {
|
||||
RTC_DCHECK(false) << "CreateThread failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Stop() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
if (thread_) {
|
||||
// Set stop_ to |true| on the worker thread.
|
||||
QueueUserAPC(&RaiseFlag, thread_, reinterpret_cast<ULONG_PTR>(&stop_));
|
||||
WaitForSingleObject(thread_, INFINITE);
|
||||
CloseHandle(thread_);
|
||||
thread_ = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadWindows::SetPriority(ThreadPriority priority) {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
return thread_ && SetThreadPriority(thread_, priority);
|
||||
}
|
||||
|
||||
void ThreadWindows::Run() {
|
||||
if (!name_.empty())
|
||||
rtc::SetCurrentThreadName(name_.c_str());
|
||||
|
||||
do {
|
||||
// The interface contract of Start/Stop is that for a successfull call to
|
||||
// Start, there should be at least one call to the run function. So we
|
||||
// call the function before checking |stop_|.
|
||||
if (!run_function_(obj_))
|
||||
break;
|
||||
// Alertable sleep to permit RaiseFlag to run and update |stop_|.
|
||||
SleepEx(0, true);
|
||||
} while (!stop_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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_THREAD_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WIN_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ThreadWindows : public ThreadWrapper {
|
||||
public:
|
||||
ThreadWindows(ThreadRunFunction func, void* obj, const char* thread_name);
|
||||
~ThreadWindows() override;
|
||||
|
||||
bool Start() override;
|
||||
bool Stop() override;
|
||||
|
||||
bool SetPriority(ThreadPriority priority) override;
|
||||
|
||||
protected:
|
||||
void Run();
|
||||
|
||||
private:
|
||||
static DWORD WINAPI StartThread(void* param);
|
||||
|
||||
ThreadRunFunction const run_function_;
|
||||
void* const obj_;
|
||||
bool stop_;
|
||||
HANDLE thread_;
|
||||
const std::string name_;
|
||||
rtc::ThreadChecker main_thread_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WIN_H_
|
@ -1,604 +0,0 @@
|
||||
/*
|
||||
* 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/trace_impl.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/atomicops.h"
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/source/trace_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/trace_posix.h"
|
||||
#endif // _WIN32
|
||||
|
||||
#define KEY_LEN_CHARS 31
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable:4355)
|
||||
#endif // _WIN32
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int Trace::kBoilerplateLength = 71;
|
||||
const int Trace::kTimestampPosition = 13;
|
||||
const int Trace::kTimestampLength = 12;
|
||||
volatile int Trace::level_filter_ = kTraceDefault;
|
||||
|
||||
// Construct On First Use idiom. Avoids "static initialization order fiasco".
|
||||
TraceImpl* TraceImpl::StaticInstance(CountOperation count_operation,
|
||||
const TraceLevel level) {
|
||||
// Sanities to avoid taking lock unless absolutely necessary (for
|
||||
// performance reasons). count_operation == kAddRefNoCreate implies that a
|
||||
// message will be written to file.
|
||||
if ((level != kTraceAll) && (count_operation == kAddRefNoCreate)) {
|
||||
if (!(level & level_filter())) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
TraceImpl* impl =
|
||||
GetStaticInstance<TraceImpl>(count_operation);
|
||||
return impl;
|
||||
}
|
||||
|
||||
TraceImpl* TraceImpl::GetTrace(const TraceLevel level) {
|
||||
return StaticInstance(kAddRefNoCreate, level);
|
||||
}
|
||||
|
||||
TraceImpl* TraceImpl::CreateInstance() {
|
||||
#if defined(_WIN32)
|
||||
return new TraceWindows();
|
||||
#else
|
||||
return new TracePosix();
|
||||
#endif
|
||||
}
|
||||
|
||||
TraceImpl::TraceImpl()
|
||||
: callback_(NULL),
|
||||
row_count_text_(0),
|
||||
file_count_text_(0),
|
||||
trace_file_(FileWrapper::Create()) {
|
||||
}
|
||||
|
||||
TraceImpl::~TraceImpl() {
|
||||
trace_file_->Flush();
|
||||
trace_file_->CloseFile();
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddThreadId(char* trace_message) const {
|
||||
uint32_t thread_id = ThreadWrapper::GetThreadId();
|
||||
// Messages is 12 characters.
|
||||
return sprintf(trace_message, "%10u; ", thread_id);
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddLevel(char* sz_message, const TraceLevel level) const {
|
||||
const int kMessageLength = 12;
|
||||
switch (level) {
|
||||
case kTraceTerseInfo:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(sz_message, ' ', kMessageLength);
|
||||
sz_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceStateInfo:
|
||||
sprintf(sz_message, "STATEINFO ; ");
|
||||
break;
|
||||
case kTraceWarning:
|
||||
sprintf(sz_message, "WARNING ; ");
|
||||
break;
|
||||
case kTraceError:
|
||||
sprintf(sz_message, "ERROR ; ");
|
||||
break;
|
||||
case kTraceCritical:
|
||||
sprintf(sz_message, "CRITICAL ; ");
|
||||
break;
|
||||
case kTraceInfo:
|
||||
sprintf(sz_message, "DEBUGINFO ; ");
|
||||
break;
|
||||
case kTraceModuleCall:
|
||||
sprintf(sz_message, "MODULECALL; ");
|
||||
break;
|
||||
case kTraceMemory:
|
||||
sprintf(sz_message, "MEMORY ; ");
|
||||
break;
|
||||
case kTraceTimer:
|
||||
sprintf(sz_message, "TIMER ; ");
|
||||
break;
|
||||
case kTraceStream:
|
||||
sprintf(sz_message, "STREAM ; ");
|
||||
break;
|
||||
case kTraceApiCall:
|
||||
sprintf(sz_message, "APICALL ; ");
|
||||
break;
|
||||
case kTraceDebug:
|
||||
sprintf(sz_message, "DEBUG ; ");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
// All messages are 12 characters.
|
||||
return kMessageLength;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddModuleAndId(char* trace_message,
|
||||
const TraceModule module,
|
||||
const int32_t id) const {
|
||||
// Use long int to prevent problems with different definitions of
|
||||
// int32_t.
|
||||
// TODO(hellner): is this actually a problem? If so, it should be better to
|
||||
// clean up int32_t
|
||||
const long int idl = id;
|
||||
const int kMessageLength = 25;
|
||||
if (idl != -1) {
|
||||
const unsigned long int id_engine = id >> 16;
|
||||
const unsigned long int id_channel = id & 0xffff;
|
||||
|
||||
switch (module) {
|
||||
case kTraceUndefined:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(trace_message, ' ', kMessageLength);
|
||||
trace_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceVoice:
|
||||
sprintf(trace_message, " VOICE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf(trace_message, " VIDEO:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf(trace_message, " UTILITY:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf(trace_message, " RTP/RTCP:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf(trace_message, " TRANSPORT:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf(trace_message, "AUDIO CODING:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf(trace_message, " SRTP:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf(trace_message, " AUDIO MIX/S:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf(trace_message, " AUDIO MIX/C:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf(trace_message, "VIDEO CODING:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
// Print sleep time and API call
|
||||
sprintf(trace_message, " VIDEO MIX:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf(trace_message, " FILE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioProcessing:
|
||||
sprintf(trace_message, " AUDIO PROC:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf(trace_message, "AUDIO DEVICE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf(trace_message, "VIDEO RENDER:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf(trace_message, "VIDEO CAPTUR:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceRemoteBitrateEstimator:
|
||||
sprintf(trace_message, " BWE RBE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (module) {
|
||||
case kTraceUndefined:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(trace_message, ' ', kMessageLength);
|
||||
trace_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceVoice:
|
||||
sprintf(trace_message, " VOICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf(trace_message, " VIDEO:%11ld;", idl);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf(trace_message, " UTILITY:%11ld;", idl);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf(trace_message, " RTP/RTCP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf(trace_message, " TRANSPORT:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf(trace_message, "AUDIO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf(trace_message, " SRTP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf(trace_message, " AUDIO MIX/S:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf(trace_message, " AUDIO MIX/C:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf(trace_message, "VIDEO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
sprintf(trace_message, " VIDEO MIX:%11ld;", idl);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf(trace_message, " FILE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioProcessing:
|
||||
sprintf(trace_message, " AUDIO PROC:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf(trace_message, "AUDIO DEVICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf(trace_message, "VIDEO RENDER:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf(trace_message, "VIDEO CAPTUR:%11ld;", idl);
|
||||
break;
|
||||
case kTraceRemoteBitrateEstimator:
|
||||
sprintf(trace_message, " BWE RBE:%11ld;", idl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return kMessageLength;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::SetTraceFileImpl(const char* file_name_utf8,
|
||||
const bool add_file_counter) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
|
||||
trace_file_->Flush();
|
||||
trace_file_->CloseFile();
|
||||
|
||||
if (file_name_utf8) {
|
||||
if (add_file_counter) {
|
||||
file_count_text_ = 1;
|
||||
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize];
|
||||
CreateFileName(file_name_utf8, file_name_with_counter_utf8,
|
||||
file_count_text_);
|
||||
if (trace_file_->OpenFile(file_name_with_counter_utf8, false, false,
|
||||
true) == -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
file_count_text_ = 0;
|
||||
if (trace_file_->OpenFile(file_name_utf8, false, false, true) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
row_count_text_ = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::TraceFileImpl(
|
||||
char file_name_utf8[FileWrapper::kMaxFileNameSize]) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
return trace_file_->FileName(file_name_utf8, FileWrapper::kMaxFileNameSize);
|
||||
}
|
||||
|
||||
int32_t TraceImpl::SetTraceCallbackImpl(TraceCallback* callback) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
callback_ = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddMessage(
|
||||
char* trace_message,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t written_so_far) const {
|
||||
int length = 0;
|
||||
if (written_so_far >= WEBRTC_TRACE_MAX_MESSAGE_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
// - 2 to leave room for newline and NULL termination.
|
||||
#ifdef _WIN32
|
||||
length = _snprintf(trace_message,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2,
|
||||
"%s", msg);
|
||||
if (length < 0) {
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2;
|
||||
trace_message[length] = 0;
|
||||
}
|
||||
#else
|
||||
length = snprintf(trace_message,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2,
|
||||
"%s", msg);
|
||||
if (length < 0 ||
|
||||
length > WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2) {
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2;
|
||||
trace_message[length] = 0;
|
||||
}
|
||||
#endif
|
||||
// Length with NULL termination.
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
void TraceImpl::AddMessageToList(
|
||||
const char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t length,
|
||||
const TraceLevel level) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
if (callback_)
|
||||
callback_->Print(level, trace_message, length);
|
||||
WriteToFile(trace_message, length);
|
||||
}
|
||||
|
||||
void TraceImpl::WriteToFile(const char* msg, uint16_t length) {
|
||||
if (!trace_file_->Open())
|
||||
return;
|
||||
|
||||
if (row_count_text_ > WEBRTC_TRACE_MAX_FILE_SIZE) {
|
||||
// wrap file
|
||||
row_count_text_ = 0;
|
||||
trace_file_->Flush();
|
||||
|
||||
if (file_count_text_ == 0) {
|
||||
trace_file_->Rewind();
|
||||
} else {
|
||||
char old_file_name[FileWrapper::kMaxFileNameSize];
|
||||
char new_file_name[FileWrapper::kMaxFileNameSize];
|
||||
|
||||
// get current name
|
||||
trace_file_->FileName(old_file_name, FileWrapper::kMaxFileNameSize);
|
||||
trace_file_->CloseFile();
|
||||
|
||||
file_count_text_++;
|
||||
|
||||
UpdateFileName(old_file_name, new_file_name, file_count_text_);
|
||||
|
||||
if (trace_file_->OpenFile(new_file_name, false, false, true) == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row_count_text_ == 0) {
|
||||
char message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
|
||||
int32_t length = AddDateTimeInfo(message);
|
||||
if (length != -1) {
|
||||
message[length] = 0;
|
||||
message[length - 1] = '\n';
|
||||
trace_file_->Write(message, length);
|
||||
row_count_text_++;
|
||||
}
|
||||
}
|
||||
|
||||
char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
memcpy(trace_message, msg, length);
|
||||
trace_message[length] = 0;
|
||||
trace_message[length - 1] = '\n';
|
||||
trace_file_->Write(trace_message, length);
|
||||
row_count_text_++;
|
||||
}
|
||||
|
||||
void TraceImpl::AddImpl(const TraceLevel level,
|
||||
const TraceModule module,
|
||||
const int32_t id,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE]) {
|
||||
if (!TraceCheck(level))
|
||||
return;
|
||||
|
||||
char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* message_ptr = &trace_message[0];
|
||||
int32_t len = AddLevel(message_ptr, level);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
int32_t ack_len = len;
|
||||
|
||||
len = AddTime(message_ptr, level);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddModuleAndId(message_ptr, module, id);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddThreadId(message_ptr);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddMessage(message_ptr, msg, static_cast<uint16_t>(ack_len));
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
ack_len += len;
|
||||
AddMessageToList(trace_message, static_cast<uint16_t>(ack_len), level);
|
||||
}
|
||||
|
||||
bool TraceImpl::TraceCheck(const TraceLevel level) const {
|
||||
return (level & level_filter()) ? true : false;
|
||||
}
|
||||
|
||||
bool TraceImpl::UpdateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const {
|
||||
int32_t length = (int32_t)strlen(file_name_utf8);
|
||||
if (length < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t length_without_file_ending = length - 1;
|
||||
while (length_without_file_ending > 0) {
|
||||
if (file_name_utf8[length_without_file_ending] == '.') {
|
||||
break;
|
||||
} else {
|
||||
length_without_file_ending--;
|
||||
}
|
||||
}
|
||||
if (length_without_file_ending == 0) {
|
||||
length_without_file_ending = length;
|
||||
}
|
||||
int32_t length_to_ = length_without_file_ending - 1;
|
||||
while (length_to_ > 0) {
|
||||
if (file_name_utf8[length_to_] == '_') {
|
||||
break;
|
||||
} else {
|
||||
length_to_--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(file_name_with_counter_utf8, file_name_utf8, length_to_);
|
||||
sprintf(file_name_with_counter_utf8 + length_to_, "_%lu%s",
|
||||
static_cast<long unsigned int>(new_count),
|
||||
file_name_utf8 + length_without_file_ending);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceImpl::CreateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const {
|
||||
int32_t length = (int32_t)strlen(file_name_utf8);
|
||||
if (length < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t length_without_file_ending = length - 1;
|
||||
while (length_without_file_ending > 0) {
|
||||
if (file_name_utf8[length_without_file_ending] == '.') {
|
||||
break;
|
||||
} else {
|
||||
length_without_file_ending--;
|
||||
}
|
||||
}
|
||||
if (length_without_file_ending == 0) {
|
||||
length_without_file_ending = length;
|
||||
}
|
||||
memcpy(file_name_with_counter_utf8, file_name_utf8,
|
||||
length_without_file_ending);
|
||||
sprintf(file_name_with_counter_utf8 + length_without_file_ending, "_%lu%s",
|
||||
static_cast<long unsigned int>(new_count),
|
||||
file_name_utf8 + length_without_file_ending);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::CreateTrace() {
|
||||
TraceImpl::StaticInstance(kAddRef);
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::ReturnTrace() {
|
||||
TraceImpl::StaticInstance(kRelease);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t Trace::TraceFile(char file_name[FileWrapper::kMaxFileNameSize]) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->TraceFileImpl(file_name);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::set_level_filter(int filter) {
|
||||
rtc::AtomicOps::ReleaseStore(&level_filter_, filter);
|
||||
}
|
||||
|
||||
// static
|
||||
int Trace::level_filter() {
|
||||
return rtc::AtomicOps::AcquireLoad(&level_filter_);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t Trace::SetTraceFile(const char* file_name,
|
||||
const bool add_file_counter) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->SetTraceFileImpl(file_name, add_file_counter);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t Trace::SetTraceCallback(TraceCallback* callback) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->SetTraceCallbackImpl(callback);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Trace::Add(const TraceLevel level, const TraceModule module,
|
||||
const int32_t id, const char* msg, ...) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace(level);
|
||||
if (trace) {
|
||||
if (trace->TraceCheck(level)) {
|
||||
char temp_buff[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* buff = 0;
|
||||
if (msg) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
#ifdef _WIN32
|
||||
_vsnprintf(temp_buff, WEBRTC_TRACE_MAX_MESSAGE_SIZE - 1, msg, args);
|
||||
#else
|
||||
vsnprintf(temp_buff, WEBRTC_TRACE_MAX_MESSAGE_SIZE - 1, msg, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
buff = temp_buff;
|
||||
}
|
||||
trace->AddImpl(level, module, id, buff);
|
||||
}
|
||||
ReturnTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* 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_TRACE_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/static_instance.h"
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#define WEBRTC_TRACE_MAX_MESSAGE_SIZE 1024
|
||||
// Total buffer size is WEBRTC_TRACE_NUM_ARRAY (number of buffer partitions) *
|
||||
// WEBRTC_TRACE_MAX_QUEUE (number of lines per buffer partition) *
|
||||
// WEBRTC_TRACE_MAX_MESSAGE_SIZE (number of 1 byte charachters per line) =
|
||||
// 1 or 4 Mbyte.
|
||||
|
||||
#define WEBRTC_TRACE_MAX_FILE_SIZE 100*1000
|
||||
// Number of rows that may be written to file. On average 110 bytes per row (max
|
||||
// 256 bytes per row). So on average 110*100*1000 = 11 Mbyte, max 256*100*1000 =
|
||||
// 25.6 Mbyte
|
||||
|
||||
class TraceImpl : public Trace {
|
||||
public:
|
||||
virtual ~TraceImpl();
|
||||
|
||||
static TraceImpl* CreateInstance();
|
||||
static TraceImpl* GetTrace(const TraceLevel level = kTraceAll);
|
||||
|
||||
int32_t SetTraceFileImpl(const char* file_name, const bool add_file_counter);
|
||||
int32_t TraceFileImpl(char file_name[FileWrapper::kMaxFileNameSize]);
|
||||
|
||||
int32_t SetTraceCallbackImpl(TraceCallback* callback);
|
||||
|
||||
void AddImpl(const TraceLevel level, const TraceModule module,
|
||||
const int32_t id, const char* msg);
|
||||
|
||||
bool TraceCheck(const TraceLevel level) const;
|
||||
|
||||
protected:
|
||||
TraceImpl();
|
||||
|
||||
static TraceImpl* StaticInstance(CountOperation count_operation,
|
||||
const TraceLevel level = kTraceAll);
|
||||
|
||||
int32_t AddThreadId(char* trace_message) const;
|
||||
|
||||
// OS specific implementations.
|
||||
virtual int32_t AddTime(char* trace_message,
|
||||
const TraceLevel level) const = 0;
|
||||
|
||||
virtual int32_t AddDateTimeInfo(char* trace_message) const = 0;
|
||||
|
||||
private:
|
||||
friend class Trace;
|
||||
|
||||
int32_t AddLevel(char* sz_message, const TraceLevel level) const;
|
||||
|
||||
int32_t AddModuleAndId(char* trace_message, const TraceModule module,
|
||||
const int32_t id) const;
|
||||
|
||||
int32_t AddMessage(char* trace_message,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t written_so_far) const;
|
||||
|
||||
void AddMessageToList(
|
||||
const char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t length,
|
||||
const TraceLevel level);
|
||||
|
||||
bool UpdateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const;
|
||||
|
||||
bool CreateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const;
|
||||
|
||||
void WriteToFile(const char* msg, uint16_t length)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
TraceCallback* callback_ GUARDED_BY(crit_);
|
||||
uint32_t row_count_text_ GUARDED_BY(crit_);
|
||||
uint32_t file_count_text_ GUARDED_BY(crit_);
|
||||
|
||||
const rtc::scoped_ptr<FileWrapper> trace_file_ GUARDED_BY(crit_);
|
||||
rtc::CriticalSection crit_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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/trace_posix.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TracePosix::TracePosix()
|
||||
: crit_sect_(*CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
struct timeval system_time_high_res;
|
||||
gettimeofday(&system_time_high_res, 0);
|
||||
prev_api_tick_count_ = prev_tick_count_ = system_time_high_res.tv_sec;
|
||||
}
|
||||
|
||||
TracePosix::~TracePosix() {
|
||||
delete &crit_sect_;
|
||||
}
|
||||
|
||||
int32_t TracePosix::AddTime(char* trace_message, const TraceLevel level) const {
|
||||
struct timeval system_time_high_res;
|
||||
if (gettimeofday(&system_time_high_res, 0) == -1) {
|
||||
return -1;
|
||||
}
|
||||
struct tm buffer;
|
||||
const struct tm* system_time =
|
||||
localtime_r(&system_time_high_res.tv_sec, &buffer);
|
||||
|
||||
const uint32_t ms_time = system_time_high_res.tv_usec / 1000;
|
||||
uint32_t prev_tickCount = 0;
|
||||
{
|
||||
CriticalSectionScoped lock(&crit_sect_);
|
||||
if (level == kTraceApiCall) {
|
||||
prev_tickCount = prev_tick_count_;
|
||||
prev_tick_count_ = ms_time;
|
||||
} else {
|
||||
prev_tickCount = prev_api_tick_count_;
|
||||
prev_api_tick_count_ = ms_time;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t dw_delta_time = ms_time - prev_tickCount;
|
||||
if (prev_tickCount == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wraparound or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5lu) ", system_time->tm_hour,
|
||||
system_time->tm_min, system_time->tm_sec, ms_time,
|
||||
static_cast<unsigned long>(dw_delta_time));
|
||||
// Messages are 22 characters.
|
||||
return 22;
|
||||
}
|
||||
|
||||
int32_t TracePosix::AddDateTimeInfo(char* trace_message) const {
|
||||
time_t t;
|
||||
time(&t);
|
||||
char buffer[26]; // man ctime says buffer should have room for >=26 bytes.
|
||||
sprintf(trace_message, "Local Date: %s", ctime_r(&t, buffer));
|
||||
int32_t len = static_cast<int32_t>(strlen(trace_message));
|
||||
|
||||
if ('\n' == trace_message[len - 1]) {
|
||||
trace_message[len - 1] = '\0';
|
||||
--len;
|
||||
}
|
||||
|
||||
// Messages is 12 characters.
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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_TRACE_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TracePosix : public TraceImpl {
|
||||
public:
|
||||
TracePosix();
|
||||
~TracePosix() override;
|
||||
|
||||
// This method can be called on several different threads different from
|
||||
// the creating thread.
|
||||
int32_t AddTime(char* trace_message, const TraceLevel level) const override;
|
||||
|
||||
int32_t AddDateTimeInfo(char* trace_message) const override;
|
||||
|
||||
private:
|
||||
volatile mutable uint32_t prev_api_tick_count_;
|
||||
volatile mutable uint32_t prev_tick_count_;
|
||||
|
||||
CriticalSectionWrapper& crit_sect_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_POSIX_H_
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* 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/trace_win.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
TraceWindows::TraceWindows()
|
||||
: prev_api_tick_count_(0),
|
||||
prev_tick_count_(0) {
|
||||
}
|
||||
|
||||
TraceWindows::~TraceWindows() {
|
||||
}
|
||||
|
||||
int32_t TraceWindows::AddTime(char* trace_message,
|
||||
const TraceLevel level) const {
|
||||
uint32_t dw_current_time = timeGetTime();
|
||||
SYSTEMTIME system_time;
|
||||
GetSystemTime(&system_time);
|
||||
|
||||
if (level == kTraceApiCall) {
|
||||
uint32_t dw_delta_time = dw_current_time - prev_tick_count_;
|
||||
prev_tick_count_ = dw_current_time;
|
||||
|
||||
if (prev_tick_count_ == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wrap-around or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5u) ", system_time.wHour,
|
||||
system_time.wMinute, system_time.wSecond,
|
||||
system_time.wMilliseconds, dw_delta_time);
|
||||
} else {
|
||||
uint32_t dw_delta_time = dw_current_time - prev_api_tick_count_;
|
||||
prev_api_tick_count_ = dw_current_time;
|
||||
|
||||
if (prev_api_tick_count_ == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wraparound or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5u) ", system_time.wHour,
|
||||
system_time.wMinute, system_time.wSecond,
|
||||
system_time.wMilliseconds, dw_delta_time);
|
||||
}
|
||||
return 22;
|
||||
}
|
||||
|
||||
int32_t TraceWindows::AddDateTimeInfo(char* trace_message) const {
|
||||
prev_api_tick_count_ = timeGetTime();
|
||||
prev_tick_count_ = prev_api_tick_count_;
|
||||
|
||||
SYSTEMTIME sys_time;
|
||||
GetLocalTime(&sys_time);
|
||||
|
||||
TCHAR sz_date_str[20];
|
||||
TCHAR sz_time_str[20];
|
||||
|
||||
// Create date string (e.g. Apr 04 2002)
|
||||
GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &sys_time, TEXT("MMM dd yyyy"),
|
||||
sz_date_str, 20);
|
||||
|
||||
// Create time string (e.g. 15:32:08)
|
||||
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &sys_time, TEXT("HH':'mm':'ss"),
|
||||
sz_time_str, 20);
|
||||
|
||||
sprintf(trace_message, "Local Date: %ls Local Time: %ls", sz_date_str,
|
||||
sz_time_str);
|
||||
|
||||
// Include NULL termination (hence + 1).
|
||||
return static_cast<int32_t>(strlen(trace_message) + 1);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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_TRACE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TraceWindows : public TraceImpl {
|
||||
public:
|
||||
TraceWindows();
|
||||
virtual ~TraceWindows();
|
||||
|
||||
virtual int32_t AddTime(char* trace_message, const TraceLevel level) const;
|
||||
|
||||
virtual int32_t AddDateTimeInfo(char* trace_message) const;
|
||||
private:
|
||||
volatile mutable uint32_t prev_api_tick_count_;
|
||||
volatile mutable uint32_t prev_tick_count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
Reference in New Issue
Block a user