Update audio_processing module

Corresponds to upstream commit 524e9b043e7e86fd72353b987c9d5f6a1ebf83e1

Update notes:

 * Pull in third party license file

 * Replace .gypi files with BUILD.gn to keep track of what changes
   upstream

 * Bunch of new filse pulled in as dependencies

 * Won't build yet due to changes needed on top of these
This commit is contained in:
Arun Raghavan
2015-10-13 17:25:22 +05:30
parent 5ae7a5d6cd
commit 753eada3aa
324 changed files with 52533 additions and 16117 deletions

View File

@ -1,13 +1,53 @@
noinst_LTLIBRARIES = libsystem_wrappers.la
libsystem_wrappers_la_SOURCES = interface/cpu_features_wrapper.h \
noinst_HEADERS = interface/aligned_array.h \
interface/compile_assert_c.h \
interface/scoped_vector.h \
interface/stl_util.h
libsystem_wrappers_la_SOURCES = interface/aligned_malloc.h \
interface/cpu_features_wrapper.h \
interface/critical_section_wrapper.h \
interface/file_wrapper.h \
interface/logging.h \
interface/metrics.h \
interface/sleep.h \
interface/trace.h \
source/aligned_malloc.cc \
source/cpu_features.cc \
source/event.cc \
source/event_timer_posix.h \
source/event_timer_win.h \
source/file_impl.cc \
source/file_impl.h \
source/critical_section.cc \
source/critical_section_posix.h \
source/critical_section_windows.h
source/critical_section_win.h \
source/logging.cc \
source/metrics_default.cc \
source/rw_lock_generic.h \
source/rw_lock_posix.h \
source/rw_lock_win.h \
source/sleep.cc \
source/thread.cc \
source/thread_posix.h \
source/thread_win.h
source/trace_impl.cc \
source/trace_impl.h \
source/trace_posix.h \
source/trace_win.h
# This assumes that we want the POSIX implementation -- should eventually be
# converted to a conditional to include Windows support
libsystem_wrappers_la_SOURCES += source/critical_section_posix.cc
libsystem_wrappers_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS) \
-I$(srcdir)/interface
libsystem_wrappers_la_SOURCES += source/critical_section_posix.cc \
source/event_timer_posix.cc \
source/rw_lock_posix.cc \
source/thread_posix.cc \
source/trace_posix.cc
libsystem_wrappers_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
EXTRA_DIST = source/critical_section_win.cc \
source/event_timer_win.cc \
source/rw_lock_generic.cc \
source/rw_lock_win.cc \
source/thread_win.cc \
source/trace_win.cc

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_ARRAY_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_ARRAY_
#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/interface/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_INTERFACE_ALIGNED_ARRAY_

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
// The functions declared here
// 1) Allocates block of aligned memory.
// 2) Re-calculates a pointer such that it is aligned to a higher or equal
// address.
// Note: alignment must be a power of two. The alignment is in bytes.
#include <stddef.h>
namespace webrtc {
// Returns a pointer to the first boundry of |alignment| bytes following the
// address of |ptr|.
// Note that there is no guarantee that the memory in question is available.
// |ptr| has no requirements other than it can't be NULL.
void* GetRightAlign(const void* ptr, size_t alignment);
// Allocates memory of |size| bytes aligned on an |alignment| boundry.
// The return value is a pointer to the memory. Note that the memory must
// be de-allocated using AlignedFree.
void* AlignedMalloc(size_t size, size_t alignment);
// De-allocates memory created using the AlignedMalloc() API.
void AlignedFree(void* mem_block);
// Templated versions to facilitate usage of aligned malloc without casting
// to and from void*.
template<typename T>
T* GetRightAlign(const T* ptr, size_t alignment) {
return reinterpret_cast<T*>(GetRightAlign(reinterpret_cast<const void*>(ptr),
alignment));
}
template<typename T>
T* AlignedMalloc(size_t size, size_t alignment) {
return reinterpret_cast<T*>(AlignedMalloc(size, alignment));
}
// Deleter for use with scoped_ptr. E.g., use as
// scoped_ptr<Foo, AlignedFreeDeleter> foo;
struct AlignedFreeDeleter {
inline void operator()(void* ptr) const {
AlignedFree(ptr);
}
};
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_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_INTERFACE_COMPILE_ASSERT_H_

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
namespace webrtc {
enum EventTypeWrapper {
kEventSignaled = 1,
kEventError = 2,
kEventTimeout = 3
};
#define WEBRTC_EVENT_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_INTERFACE_EVENT_WRAPPER_H_

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
#include <stddef.h>
#include <stdio.h>
#include "webrtc/common_types.h"
#include "webrtc/typedefs.h"
// Implementation of an InStream and OutStream that can read (exclusive) or
// write from/to a file.
namespace webrtc {
class FileWrapper : public InStream, public OutStream {
public:
static const size_t kMaxFileNameSize = 1024;
// Factory method. Constructor disabled.
static FileWrapper* Create();
// Returns true if a file has been opened.
virtual bool Open() const = 0;
// Opens a file in read or write mode, decided by the read_only parameter.
virtual int OpenFile(const char* file_name_utf8,
bool read_only,
bool loop = false,
bool text = false) = 0;
// Initializes the wrapper from an existing handle. |read_only| must match in
// the mode the file was opened in. If |manage_file| is true, the wrapper
// takes ownership of |handle| and closes it in CloseFile().
virtual int OpenFromFileHandle(FILE* handle,
bool manage_file,
bool read_only,
bool loop = false) = 0;
virtual int CloseFile() = 0;
// Limits the file size to |bytes|. Writing will fail after the cap
// is hit. Pass zero to use an unlimited size.
virtual int SetMaxFileSize(size_t bytes) = 0;
// Flush any pending writes.
virtual int Flush() = 0;
// Returns the opened file's name in |file_name_utf8|. Provide the size of
// the buffer in bytes in |size|. The name will be truncated if |size| is
// too small.
virtual int FileName(char* file_name_utf8,
size_t size) const = 0;
// Write |format| to the opened file. Arguments are taken in the same manner
// as printf. That is, supply a format string containing text and
// specifiers. Returns the number of characters written or -1 on error.
virtual int WriteText(const char* format, ...) = 0;
// Inherited from 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_INTERFACE_FILE_WRAPPER_H_

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// This is a highly stripped-down version of libjingle's talk/base/logging.h.
// It is a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
// semantics to ease a transition to that format.
// NOTE: LS_INFO maps to a new trace level which should be reserved for
// infrequent, non-verbose logs. The other levels below kTraceWarning have been
// rendered essentially useless due to their verbosity. Carefully consider the
// impact of adding a new LS_INFO log. If it will be logged at anything
// approaching a frame or packet frequency, use LS_VERBOSE if necessary, or
// preferably, do not log at all.
// LOG(...) an ostream target that can be used to send formatted
// output to a variety of logging targets, such as debugger console, stderr,
// file, or any StreamInterface.
// The severity level passed as the first argument to the LOGging
// functions is used as a filter, to limit the verbosity of the logging.
// Static members of LogMessage documented below are used to control the
// verbosity and target of the output.
// There are several variations on the LOG macro which facilitate logging
// of common error conditions, detailed below.
// LOG(sev) logs the given stream at severity "sev", which must be a
// compile-time constant of the LoggingSeverity type, without the namespace
// prefix.
// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
// type (basically, it just doesn't prepend the namespace).
// LOG_F(sev) Like LOG(), but includes the name of the current function.
// Additional helper macros added by WebRTC:
// LOG_API is a shortcut for API call logging. Pass in the input parameters of
// the method. For example:
// Foo(int bar, int baz) {
// LOG_API2(bar, baz);
// }
//
// LOG_FERR is a shortcut for logging a failed function call. For example:
// if (!Foo(bar)) {
// LOG_FERR1(LS_WARNING, Foo, bar);
// }
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
#include <sstream>
namespace webrtc {
//////////////////////////////////////////////////////////////////////
// Note that the non-standard LoggingSeverity aliases exist because they are
// still in broad use. The meanings of the levels are:
// LS_SENSITIVE: Information which should only be logged with the consent
// of the user, due to privacy concerns.
// LS_VERBOSE: This level is for data which we do not want to appear in the
// normal debug log, but should appear in diagnostic logs.
// LS_INFO: Chatty level used in debugging for all sorts of things, the default
// in debug builds.
// LS_WARNING: Something that may warrant investigation.
// LS_ERROR: Something that should not have occurred.
enum LoggingSeverity {
LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR
};
class LogMessage {
public:
LogMessage(const char* file, int line, LoggingSeverity sev);
~LogMessage();
static bool Loggable(LoggingSeverity sev);
std::ostream& stream() { return print_stream_; }
private:
// The ostream that buffers the formatted message before output
std::ostringstream print_stream_;
// The severity level of this message
LoggingSeverity severity_;
};
//////////////////////////////////////////////////////////////////////
// Macros which automatically disable logging when WEBRTC_LOGGING == 0
//////////////////////////////////////////////////////////////////////
#ifndef LOG
// The following non-obvious technique for implementation of a
// conditional log stream was stolen from google3/base/logging.h.
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
LogMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) { }
};
#if defined(WEBRTC_RESTRICT_LOGGING)
// This should compile away logs matching the following condition.
#define RESTRICT_LOGGING_PRECONDITION(sev) \
sev < webrtc::LS_INFO ? (void) 0 :
#else
#define RESTRICT_LOGGING_PRECONDITION(sev)
#endif
#define LOG_SEVERITY_PRECONDITION(sev) \
RESTRICT_LOGGING_PRECONDITION(sev) !(webrtc::LogMessage::Loggable(sev)) \
? (void) 0 \
: webrtc::LogMessageVoidify() &
#define LOG(sev) \
LOG_SEVERITY_PRECONDITION(webrtc::sev) \
webrtc::LogMessage(__FILE__, __LINE__, webrtc::sev).stream()
// The _V version is for when a variable is passed in. It doesn't do the
// namespace concatination.
#define LOG_V(sev) \
LOG_SEVERITY_PRECONDITION(sev) \
webrtc::LogMessage(__FILE__, __LINE__, sev).stream()
// The _F version prefixes the message with the current function name.
#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F)
#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
#else
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
#endif
#define LOG_API0() LOG_F(LS_VERBOSE)
#define LOG_API1(v1) LOG_API0() << #v1 << "=" << v1
#define LOG_API2(v1, v2) LOG_API1(v1) \
<< ", " << #v2 << "=" << v2
#define LOG_API3(v1, v2, v3) LOG_API2(v1, v2) \
<< ", " << #v3 << "=" << v3
#define LOG_FERR0(sev, func) LOG(sev) << #func << " failed"
#define LOG_FERR1(sev, func, v1) LOG_FERR0(sev, func) \
<< ": " << #v1 << "=" << v1
#define LOG_FERR2(sev, func, v1, v2) LOG_FERR1(sev, func, v1) \
<< ", " << #v2 << "=" << v2
#define LOG_FERR3(sev, func, v1, v2, v3) LOG_FERR2(sev, func, v1, v2) \
<< ", " << #v3 << "=" << v3
#define LOG_FERR4(sev, func, v1, v2, v3, v4) LOG_FERR3(sev, func, v1, v2, v3) \
<< ", " << #v4 << "=" << v4
#endif // LOG
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_

View File

@ -0,0 +1,136 @@
//
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_METRICS_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_METRICS_H_
#include <string>
#include "webrtc/common_types.h"
// Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate
// statistics.
//
// Histogram for counters.
// RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count);
//
// Histogram for enumerators.
// The boundary should be above the max enumerator sample.
// RTC_HISTOGRAM_ENUMERATION(name, sample, boundary);
//
//
// 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).
//
//
// Example usage:
//
// RTC_HISTOGRAM_COUNTS("WebRTC.Video.NacksSent", nacks_sent, 1, 100000, 100);
//
// enum Types {
// kTypeX,
// kTypeY,
// kBoundary,
// };
//
// RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary);
// Macros for adding samples to a named histogram.
//
// 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.
// Histogram for counters.
#define RTC_HISTOGRAM_COUNTS_100(name, sample) RTC_HISTOGRAM_COUNTS( \
name, sample, 1, 100, 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))
// Histogram for percentage.
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
// Histogram for enumerators.
// |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))
#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); \
} while (0)
namespace webrtc {
namespace metrics {
// Time that should have elapsed for stats that are gathered once per call.
enum { kMinRunTimeInSeconds = 10 };
class Histogram;
// Functions for getting pointer to histogram (constructs or finds the named
// histogram).
// Get histogram for counters.
Histogram* HistogramFactoryGetCounts(
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);
// 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);
} // namespace metrics
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_METRICS_H_

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
#include "webrtc/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_INTERFACE_RW_LOCK_WRAPPER_H_

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/memory/scoped_vector.h.
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_VECTOR_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_VECTOR_H_
#include <vector>
#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/interface/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_INTERFACE_SCOPED_VECTOR_H_

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// An OS-independent sleep function.
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
namespace webrtc {
// This function sleeps for the specified number of milliseconds.
// It may return early if the thread is woken by some other event,
// such as the delivery of a signal on Unix.
void SleepMs(int msecs);
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
#include <assert.h>
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#ifdef _WIN32
#include "webrtc/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h"
#endif
namespace webrtc {
enum CountOperation {
kRelease,
kAddRef,
kAddRefNoCreate
};
enum CreateOperation {
kInstanceExists,
kCreate,
kDestroy
};
template <class T>
// Construct On First Use idiom. Avoids
// "static initialization order fiasco".
static T* GetStaticInstance(CountOperation count_operation) {
// TODO (hellner): use atomic wrapper instead.
static volatile long instance_count = 0;
static T* volatile instance = NULL;
CreateOperation state = kInstanceExists;
#ifndef _WIN32
// This memory is staticly allocated once. The application does not try to
// free this memory. This approach is taken to avoid issues with
// destruction order for statically allocated memory. The memory will be
// reclaimed by the OS and memory leak tools will not recognize memory
// reachable from statics leaked so no noise is added by doing this.
static CriticalSectionWrapper* crit_sect(
CriticalSectionWrapper::CreateCriticalSection());
CriticalSectionScoped lock(crit_sect);
if (count_operation ==
kAddRefNoCreate && instance_count == 0) {
return NULL;
}
if (count_operation ==
kAddRef ||
count_operation == kAddRefNoCreate) {
instance_count++;
if (instance_count == 1) {
state = kCreate;
}
} else {
instance_count--;
if (instance_count == 0) {
state = kDestroy;
}
}
if (state == kCreate) {
instance = T::CreateInstance();
} else if (state == kDestroy) {
T* old_instance = instance;
instance = NULL;
// The state will not change past this point. Release the critical
// section while deleting the object in case it would be blocking on
// access back to this object. (This is the case for the tracing class
// since the thread owned by the tracing class also traces).
// TODO(hellner): this is a bit out of place but here goes, de-couple
// thread implementation with trace implementation.
crit_sect->Leave();
if (old_instance) {
delete old_instance;
}
// Re-acquire the lock since the scoped critical section will release
// it.
crit_sect->Enter();
return NULL;
}
#else // _WIN32
if (count_operation ==
kAddRefNoCreate && instance_count == 0) {
return NULL;
}
if (count_operation == kAddRefNoCreate) {
if (1 == InterlockedIncrement(&instance_count)) {
// The instance has been destroyed by some other thread. Rollback.
InterlockedDecrement(&instance_count);
assert(false);
return NULL;
}
// Sanity to catch corrupt state.
if (instance == NULL) {
assert(false);
InterlockedDecrement(&instance_count);
return NULL;
}
} else if (count_operation == kAddRef) {
if (instance_count == 0) {
state = kCreate;
} else {
if (1 == InterlockedIncrement(&instance_count)) {
// InterlockedDecrement because reference count should not be
// updated just yet (that's done when the instance is created).
InterlockedDecrement(&instance_count);
state = kCreate;
}
}
} else {
int new_value = InterlockedDecrement(&instance_count);
if (new_value == 0) {
state = kDestroy;
}
}
if (state == kCreate) {
// Create instance and let whichever thread finishes first assign its
// local copy to the global instance. All other threads reclaim their
// local copy.
T* new_instance = T::CreateInstance();
if (1 == InterlockedIncrement(&instance_count)) {
InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&instance),
new_instance);
} else {
InterlockedDecrement(&instance_count);
if (new_instance) {
delete static_cast<T*>(new_instance);
}
}
} else if (state == kDestroy) {
T* old_value = static_cast<T*>(InterlockedExchangePointer(
reinterpret_cast<void * volatile*>(&instance), NULL));
if (old_value) {
delete static_cast<T*>(old_value);
}
return NULL;
}
#endif // #ifndef _WIN32
return instance;
}
} // namspace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/stl_util.h.
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
#include <assert.h>
#include <algorithm>
#include <functional>
#include <iterator>
#include <string>
#include <vector>
namespace webrtc {
// Clears internal memory of an STL object.
// STL clear()/reserve(0) does not always free internal memory allocated
// This function uses swap/destructor to ensure the internal memory is freed.
template<class T>
void STLClearObject(T* obj) {
T tmp;
tmp.swap(*obj);
// Sometimes "T tmp" allocates objects with memory (arena implementation?).
// Hence using additional reserve(0) even if it doesn't always work.
obj->reserve(0);
}
// For a range within a container of pointers, calls delete (non-array version)
// on these pointers.
// NOTE: for these three functions, we could just implement a DeleteObject
// functor and then call for_each() on the range and functor, but this
// requires us to pull in all of algorithm.h, which seems expensive.
// For hash_[multi]set, it is important that this deletes behind the iterator
// because the hash_set may call the hash function on the iterator when it is
// advanced, which could result in the hash function trying to deference a
// stale pointer.
template <class ForwardIterator>
void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) {
while (begin != end) {
ForwardIterator temp = begin;
++begin;
delete *temp;
}
}
// For a range within a container of pairs, calls delete (non-array version) on
// BOTH items in the pairs.
// NOTE: Like STLDeleteContainerPointers, it is important that this deletes
// behind the iterator because if both the key and value are deleted, the
// container may call the hash function on the iterator when it is advanced,
// which could result in the hash function trying to dereference a stale
// pointer.
template <class ForwardIterator>
void STLDeleteContainerPairPointers(ForwardIterator begin,
ForwardIterator end) {
while (begin != end) {
ForwardIterator temp = begin;
++begin;
delete temp->first;
delete temp->second;
}
}
// For a range within a container of pairs, calls delete (non-array version) on
// the FIRST item in the pairs.
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
template <class ForwardIterator>
void STLDeleteContainerPairFirstPointers(ForwardIterator begin,
ForwardIterator end) {
while (begin != end) {
ForwardIterator temp = begin;
++begin;
delete temp->first;
}
}
// For a range within a container of pairs, calls delete.
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
// Deleting the value does not always invalidate the iterator, but it may
// do so if the key is a pointer into the value object.
template <class ForwardIterator>
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
ForwardIterator end) {
while (begin != end) {
ForwardIterator temp = begin;
++begin;
delete temp->second;
}
}
// To treat a possibly-empty vector as an array, use these functions.
// If you know the array will never be empty, you can use &*v.begin()
// directly, but that is undefined behaviour if |v| is empty.
template<typename T>
inline T* vector_as_array(std::vector<T>* v) {
return v->empty() ? NULL : &*v->begin();
}
template<typename T>
inline const T* vector_as_array(const std::vector<T>* v) {
return v->empty() ? NULL : &*v->begin();
}
// Return a mutable char* pointing to a string's internal buffer,
// which may not be null-terminated. Writing through this pointer will
// modify the string.
//
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
// next call to a string method that invalidates iterators.
//
// As of 2006-04, there is no standard-blessed way of getting a
// mutable reference to a string's internal buffer. However, issue 530
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
// proposes this as the method. According to Matt Austern, this should
// already work on all current implementations.
inline char* string_as_array(std::string* str) {
// DO NOT USE const_cast<char*>(str->data())
return str->empty() ? NULL : &*str->begin();
}
// The following functions are useful for cleaning up STL containers whose
// elements point to allocated memory.
// STLDeleteElements() deletes all the elements in an STL container and clears
// the container. This function is suitable for use with a vector, set,
// hash_set, or any other STL container which defines sensible begin(), end(),
// and clear() methods.
//
// If container is NULL, this function is a no-op.
//
// As an alternative to calling STLDeleteElements() directly, consider
// STLElementDeleter (defined below), which ensures that your container's
// elements are deleted when the STLElementDeleter goes out of scope.
template <class T>
void STLDeleteElements(T* container) {
if (!container)
return;
STLDeleteContainerPointers(container->begin(), container->end());
container->clear();
}
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
// deletes all the "value" components and clears the container. Does nothing
// in the case it's given a NULL pointer.
template <class T>
void STLDeleteValues(T* container) {
if (!container)
return;
for (typename T::iterator i(container->begin()); i != container->end(); ++i)
delete i->second;
container->clear();
}
// The following classes provide a convenient way to delete all elements or
// values from STL containers when they goes out of scope. This greatly
// simplifies code that creates temporary objects and has multiple return
// statements. Example:
//
// vector<MyProto *> tmp_proto;
// STLElementDeleter<vector<MyProto *> > d(&tmp_proto);
// if (...) return false;
// ...
// return success;
// Given a pointer to an STL container this class will delete all the element
// pointers when it goes out of scope.
template<class T>
class STLElementDeleter {
public:
STLElementDeleter<T>(T* container) : container_(container) {}
~STLElementDeleter<T>() { STLDeleteElements(container_); }
private:
T* container_;
};
// Given a pointer to an STL container this class will delete all the value
// pointers when it goes out of scope.
template<class T>
class STLValueDeleter {
public:
STLValueDeleter<T>(T* container) : container_(container) {}
~STLValueDeleter<T>() { STLDeleteValues(container_); }
private:
T* container_;
};
// Test to see if a set, map, hash_set or hash_map contains a particular key.
// Returns true if the key is in the collection.
template <typename Collection, typename Key>
bool ContainsKey(const Collection& collection, const Key& key) {
return collection.find(key) != collection.end();
}
// Returns true if the container is sorted.
template <typename Container>
bool STLIsSorted(const Container& cont) {
// Note: Use reverse iterator on container to ensure we only require
// value_type to implement operator<.
return std::adjacent_find(cont.rbegin(), cont.rend(),
std::less<typename Container::value_type>())
== cont.rend();
}
// Returns a new ResultType containing the difference of two sorted containers.
template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
assert(STLIsSorted(a1));
assert(STLIsSorted(a2));
ResultType difference;
std::set_difference(a1.begin(), a1.end(),
a2.begin(), a2.end(),
std::inserter(difference, difference.end()));
return difference;
}
// Returns a new ResultType containing the union of two sorted containers.
template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) {
assert(STLIsSorted(a1));
assert(STLIsSorted(a2));
ResultType result;
std::set_union(a1.begin(), a1.end(),
a2.begin(), a2.end(),
std::inserter(result, result.end()));
return result;
}
// Returns a new ResultType containing the intersection of two sorted
// containers.
template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) {
assert(STLIsSorted(a1));
assert(STLIsSorted(a2));
ResultType result;
std::set_intersection(a1.begin(), a1.end(),
a2.begin(), a2.end(),
std::inserter(result, result.end()));
return result;
}
// Returns true if the sorted container |a1| contains all elements of the sorted
// container |a2|.
template <typename Arg1, typename Arg2>
bool STLIncludes(const Arg1& a1, const Arg2& a2) {
assert(STLIsSorted(a1));
assert(STLIsSorted(a2));
return std::includes(a1.begin(), a1.end(),
a2.begin(), a2.end());
}
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// System independant wrapper for spawning threads
// Note: the spawned thread will loop over the callback function until stopped.
// Note: The callback function is expected to return every 2 seconds or more
// often.
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
#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_INTERFACE_THREAD_WRAPPER_H_

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*
* System independent wrapper for logging runtime information to file.
* Note: All log messages will be written to the same trace file.
* Note: If too many messages are written to file there will be a build up of
* messages. Apply filtering to avoid that.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
#include "webrtc/common_types.h"
#include "webrtc/typedefs.h"
namespace webrtc {
#if defined(WEBRTC_RESTRICT_LOGGING)
// Disable all TRACE macros. The LOG macro is still functional.
#define WEBRTC_TRACE true ? (void) 0 : Trace::Add
#else
#define WEBRTC_TRACE Trace::Add
#endif
class Trace {
public:
// The length of the trace text preceeding the log message.
static const int kBoilerplateLength;
// The position of the timestamp text within a trace.
static const int kTimestampPosition;
// The length of the timestamp (without "delta" field).
static const int kTimestampLength;
// Increments the reference count to the trace.
static void CreateTrace();
// Decrements the reference count to the trace.
static void ReturnTrace();
// Note: any instance that writes to the trace file should increment and
// decrement the reference count on construction and destruction,
// respectively.
// Specifies what type of messages should be written to the trace file. The
// filter parameter is a bitmask where each message type is enumerated by the
// TraceLevel enumerator. TODO(hellner): why is the TraceLevel enumerator not
// defined in this file?
static void set_level_filter(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_INTERFACE_TRACE_H_

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/interface/aligned_malloc.h"
#include <memory.h>
#include <stdlib.h>
#if _WIN32
#include <windows.h>
#else
#include <stdint.h>
#endif
#include "webrtc/typedefs.h"
// Reference on memory alignment:
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
namespace webrtc {
uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
// The pointer should be aligned with |alignment| bytes. The - 1 guarantees
// that it is aligned towards the closest higher (right) address.
return (start_pos + alignment - 1) & ~(alignment - 1);
}
// Alignment must be an integer power of two.
bool ValidAlignment(size_t alignment) {
if (!alignment) {
return false;
}
return (alignment & (alignment - 1)) == 0;
}
void* GetRightAlign(const void* pointer, size_t alignment) {
if (!pointer) {
return NULL;
}
if (!ValidAlignment(alignment)) {
return NULL;
}
uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
}
void* AlignedMalloc(size_t size, size_t alignment) {
if (size == 0) {
return NULL;
}
if (!ValidAlignment(alignment)) {
return NULL;
}
// The memory is aligned towards the lowest address that so only
// alignment - 1 bytes needs to be allocated.
// A pointer to the start of the memory must be stored so that it can be
// retreived for deletion, ergo the sizeof(uintptr_t).
void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
if (memory_pointer == NULL) {
return NULL;
}
// Aligning after the sizeof(uintptr_t) bytes will leave room for the header
// in the same memory block.
uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
align_start_pos += sizeof(uintptr_t);
uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
// Store the address to the beginning of the memory just before the aligned
// memory.
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
void* header_pointer = reinterpret_cast<void*>(header_pos);
uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
return aligned_pointer;
}
void AlignedFree(void* mem_block) {
if (mem_block == NULL) {
return;
}
uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
// Read out the address of the AlignedMemory struct from the header.
uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
void* memory_start = reinterpret_cast<void*>(memory_start_pos);
free(memory_start);
}
} // namespace webrtc

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/interface/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

@ -0,0 +1,231 @@
/*
* 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

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include <pthread.h>
#include <time.h>
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
namespace webrtc {
enum State {
kUp = 1,
kDown = 2
};
class 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

@ -0,0 +1,78 @@
/*
* 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

@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
#include <windows.h>
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/typedefs.h"
namespace webrtc {
class 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,278 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/file_impl.h"
#include <assert.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <stdarg.h>
#include <string.h>
#endif
#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
namespace webrtc {
FileWrapper* FileWrapper::Create() {
return new FileWrapperImpl();
}
FileWrapperImpl::FileWrapperImpl()
: rw_lock_(RWLockWrapper::CreateRWLock()),
id_(NULL),
managed_file_handle_(true),
open_(false),
looping_(false),
read_only_(false),
max_size_in_bytes_(0),
size_in_bytes_(0) {
memset(file_name_utf8_, 0, kMaxFileNameSize);
}
FileWrapperImpl::~FileWrapperImpl() {
if (id_ != NULL && managed_file_handle_) {
fclose(id_);
}
}
int FileWrapperImpl::CloseFile() {
WriteLockScoped write(*rw_lock_);
return CloseFileImpl();
}
int FileWrapperImpl::Rewind() {
WriteLockScoped write(*rw_lock_);
if (looping_ || !read_only_) {
if (id_ != NULL) {
size_in_bytes_ = 0;
return fseek(id_, 0, SEEK_SET);
}
}
return -1;
}
int FileWrapperImpl::SetMaxFileSize(size_t bytes) {
WriteLockScoped write(*rw_lock_);
max_size_in_bytes_ = bytes;
return 0;
}
int FileWrapperImpl::Flush() {
WriteLockScoped write(*rw_lock_);
return FlushImpl();
}
int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const {
ReadLockScoped read(*rw_lock_);
size_t length = strlen(file_name_utf8_);
if (length > kMaxFileNameSize) {
assert(false);
return -1;
}
if (length < 1) {
return -1;
}
// Make sure to NULL terminate
if (size < length) {
length = size - 1;
}
memcpy(file_name_utf8, file_name_utf8_, length);
file_name_utf8[length] = 0;
return 0;
}
bool FileWrapperImpl::Open() const {
ReadLockScoped read(*rw_lock_);
return open_;
}
int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only,
bool loop, bool text) {
WriteLockScoped write(*rw_lock_);
if (id_ != NULL && !managed_file_handle_)
return -1;
size_t length = strlen(file_name_utf8);
if (length > kMaxFileNameSize - 1) {
return -1;
}
read_only_ = read_only;
FILE* tmp_id = NULL;
#if defined _WIN32
wchar_t wide_file_name[kMaxFileNameSize];
wide_file_name[0] = 0;
MultiByteToWideChar(CP_UTF8,
0, // UTF8 flag
file_name_utf8,
-1, // Null terminated string
wide_file_name,
kMaxFileNameSize);
if (text) {
if (read_only) {
tmp_id = _wfopen(wide_file_name, L"rt");
} else {
tmp_id = _wfopen(wide_file_name, L"wt");
}
} else {
if (read_only) {
tmp_id = _wfopen(wide_file_name, L"rb");
} else {
tmp_id = _wfopen(wide_file_name, L"wb");
}
}
#else
if (text) {
if (read_only) {
tmp_id = fopen(file_name_utf8, "rt");
} else {
tmp_id = fopen(file_name_utf8, "wt");
}
} else {
if (read_only) {
tmp_id = fopen(file_name_utf8, "rb");
} else {
tmp_id = fopen(file_name_utf8, "wb");
}
}
#endif
if (tmp_id != NULL) {
// +1 comes from copying the NULL termination character.
memcpy(file_name_utf8_, file_name_utf8, length + 1);
if (id_ != NULL) {
fclose(id_);
}
id_ = tmp_id;
managed_file_handle_ = true;
looping_ = loop;
open_ = true;
return 0;
}
return -1;
}
int FileWrapperImpl::OpenFromFileHandle(FILE* handle,
bool manage_file,
bool read_only,
bool loop) {
WriteLockScoped write(*rw_lock_);
if (!handle)
return -1;
if (id_ != NULL) {
if (managed_file_handle_)
fclose(id_);
else
return -1;
}
id_ = handle;
managed_file_handle_ = manage_file;
read_only_ = read_only;
looping_ = loop;
open_ = true;
return 0;
}
int FileWrapperImpl::Read(void* buf, 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

@ -0,0 +1,69 @@
/*
* 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/interface/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

@ -0,0 +1,62 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/interface/logging.h"
#include <string.h>
#include <sstream>
#include "webrtc/common_types.h"
#include "webrtc/system_wrappers/interface/trace.h"
namespace webrtc {
namespace {
TraceLevel WebRtcSeverity(LoggingSeverity sev) {
switch (sev) {
// TODO(ajm): SENSITIVE doesn't have a corresponding webrtc level.
case LS_SENSITIVE: return kTraceInfo;
case LS_VERBOSE: return kTraceInfo;
case LS_INFO: return kTraceTerseInfo;
case LS_WARNING: return kTraceWarning;
case LS_ERROR: return kTraceError;
default: return kTraceNone;
}
}
// 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,29 @@
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
#include "webrtc/system_wrappers/interface/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

@ -0,0 +1,77 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
namespace webrtc {
RWLockGeneric::RWLockGeneric()
: readers_active_(0),
writer_active_(false),
readers_waiting_(0),
writers_waiting_(0) {
critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
}
RWLockGeneric::~RWLockGeneric() {
delete write_condition_;
delete read_condition_;
delete critical_section_;
}
void RWLockGeneric::AcquireLockExclusive() {
CriticalSectionScoped cs(critical_section_);
if (writer_active_ || readers_active_ > 0) {
++writers_waiting_;
while (writer_active_ || readers_active_ > 0) {
write_condition_->SleepCS(*critical_section_);
}
--writers_waiting_;
}
writer_active_ = true;
}
void RWLockGeneric::ReleaseLockExclusive() {
CriticalSectionScoped cs(critical_section_);
writer_active_ = false;
if (writers_waiting_ > 0) {
write_condition_->Wake();
} else if (readers_waiting_ > 0) {
read_condition_->WakeAll();
}
}
void RWLockGeneric::AcquireLockShared() {
CriticalSectionScoped cs(critical_section_);
if (writer_active_ || writers_waiting_ > 0) {
++readers_waiting_;
while (writer_active_ || writers_waiting_ > 0) {
read_condition_->SleepCS(*critical_section_);
}
--readers_waiting_;
}
++readers_active_;
}
void RWLockGeneric::ReleaseLockShared() {
CriticalSectionScoped cs(critical_section_);
--readers_active_;
if (readers_active_ == 0 && writers_waiting_ > 0) {
write_condition_->Wake();
}
}
} // namespace webrtc

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
#include "webrtc/typedefs.h"
namespace webrtc {
class CriticalSectionWrapper;
class ConditionVariableWrapper;
class RWLockGeneric : public RWLockWrapper {
public:
RWLockGeneric();
~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

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
namespace webrtc {
RWLockPosix::RWLockPosix() : lock_() {
}
RWLockPosix::~RWLockPosix() {
pthread_rwlock_destroy(&lock_);
}
RWLockPosix* RWLockPosix::Create() {
RWLockPosix* ret_val = new RWLockPosix();
if (!ret_val->Init()) {
delete ret_val;
return NULL;
}
return ret_val;
}
bool RWLockPosix::Init() {
return pthread_rwlock_init(&lock_, 0) == 0;
}
void RWLockPosix::AcquireLockExclusive() {
pthread_rwlock_wrlock(&lock_);
}
void RWLockPosix::ReleaseLockExclusive() {
pthread_rwlock_unlock(&lock_);
}
void RWLockPosix::AcquireLockShared() {
pthread_rwlock_rdlock(&lock_);
}
void RWLockPosix::ReleaseLockShared() {
pthread_rwlock_unlock(&lock_);
}
} // namespace webrtc

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
#include "webrtc/typedefs.h"
#include <pthread.h>
namespace webrtc {
class RWLockPosix : public RWLockWrapper {
public:
static RWLockPosix* Create();
~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

@ -0,0 +1,97 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/rw_lock_win.h"
#include "webrtc/system_wrappers/interface/trace.h"
namespace webrtc {
static bool native_rw_locks_supported = false;
static bool module_load_attempted = false;
static HMODULE library = NULL;
typedef void (WINAPI* InitializeSRWLock)(PSRWLOCK);
typedef void (WINAPI* AcquireSRWLockExclusive)(PSRWLOCK);
typedef void (WINAPI* ReleaseSRWLockExclusive)(PSRWLOCK);
typedef void (WINAPI* AcquireSRWLockShared)(PSRWLOCK);
typedef void (WINAPI* ReleaseSRWLockShared)(PSRWLOCK);
InitializeSRWLock initialize_srw_lock;
AcquireSRWLockExclusive acquire_srw_lock_exclusive;
AcquireSRWLockShared acquire_srw_lock_shared;
ReleaseSRWLockShared release_srw_lock_shared;
ReleaseSRWLockExclusive release_srw_lock_exclusive;
RWLockWin::RWLockWin() {
initialize_srw_lock(&lock_);
}
RWLockWin* RWLockWin::Create() {
if (!LoadModule()) {
return NULL;
}
return new RWLockWin();
}
void RWLockWin::AcquireLockExclusive() {
acquire_srw_lock_exclusive(&lock_);
}
void RWLockWin::ReleaseLockExclusive() {
release_srw_lock_exclusive(&lock_);
}
void RWLockWin::AcquireLockShared() {
acquire_srw_lock_shared(&lock_);
}
void RWLockWin::ReleaseLockShared() {
release_srw_lock_shared(&lock_);
}
bool RWLockWin::LoadModule() {
if (module_load_attempted) {
return native_rw_locks_supported;
}
module_load_attempted = true;
// Use native implementation if supported (i.e Vista+)
library = LoadLibrary(TEXT("Kernel32.dll"));
if (!library) {
return false;
}
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
initialize_srw_lock =
(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");
acquire_srw_lock_exclusive =
(AcquireSRWLockExclusive)GetProcAddress(library,
"AcquireSRWLockExclusive");
release_srw_lock_exclusive =
(ReleaseSRWLockExclusive)GetProcAddress(library,
"ReleaseSRWLockExclusive");
acquire_srw_lock_shared =
(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
release_srw_lock_shared =
(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");
if (initialize_srw_lock && acquire_srw_lock_exclusive &&
release_srw_lock_exclusive && acquire_srw_lock_shared &&
release_srw_lock_shared) {
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Native RW Lock");
native_rw_locks_supported = true;
}
return native_rw_locks_supported;
}
} // namespace webrtc

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
#include <Windows.h>
namespace webrtc {
class RWLockWin : public RWLockWrapper {
public:
static RWLockWin* Create();
~RWLockWin() {}
virtual void AcquireLockExclusive();
virtual void ReleaseLockExclusive();
virtual void AcquireLockShared();
virtual void ReleaseLockShared();
private:
RWLockWin();
static bool LoadModule();
SRWLOCK lock_;
};
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// An OS-independent sleep function.
#include "webrtc/system_wrappers/interface/sleep.h"
#ifdef _WIN32
// For Sleep()
#include <windows.h>
#else
// For nanosleep()
#include <time.h>
#endif
namespace webrtc {
void SleepMs(int msecs) {
#ifdef _WIN32
Sleep(msecs);
#else
struct timespec short_wait;
struct timespec remainder;
short_wait.tv_sec = msecs / 1000;
short_wait.tv_nsec = (msecs % 1000) * 1000 * 1000;
nanosleep(&short_wait, &remainder);
#endif
}
} // namespace webrtc

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/interface/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

@ -0,0 +1,166 @@
/*
* 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/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/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

@ -0,0 +1,53 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#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/interface/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

@ -0,0 +1,107 @@
/*
* 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/interface/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

@ -0,0 +1,48 @@
/*
* 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/interface/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

@ -0,0 +1,604 @@
/*
* 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

@ -0,0 +1,106 @@
/*
* 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/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/file_wrapper.h"
#include "webrtc/system_wrappers/interface/static_instance.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/system_wrappers/interface/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

@ -0,0 +1,90 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#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

@ -0,0 +1,39 @@
/*
* 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/interface/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

@ -0,0 +1,97 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/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

@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_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_