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:
Arun Raghavan
2020-10-12 18:08:02 -04:00
parent b1b02581d3
commit bcec8b0b21
859 changed files with 76187 additions and 49580 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()

View File

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

View File

@ -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, &param) != 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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