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:
@ -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
|
||||
|
88
webrtc/system_wrappers/interface/aligned_array.h
Normal file
88
webrtc/system_wrappers/interface/aligned_array.h
Normal 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_
|
59
webrtc/system_wrappers/interface/aligned_malloc.h
Normal file
59
webrtc/system_wrappers/interface/aligned_malloc.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
|
||||
// The functions declared here
|
||||
// 1) Allocates block of aligned memory.
|
||||
// 2) Re-calculates a pointer such that it is aligned to a higher or equal
|
||||
// address.
|
||||
// Note: alignment must be a power of two. The alignment is in bytes.
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Returns a pointer to the first boundry of |alignment| bytes following the
|
||||
// address of |ptr|.
|
||||
// Note that there is no guarantee that the memory in question is available.
|
||||
// |ptr| has no requirements other than it can't be NULL.
|
||||
void* GetRightAlign(const void* ptr, size_t alignment);
|
||||
|
||||
// Allocates memory of |size| bytes aligned on an |alignment| boundry.
|
||||
// The return value is a pointer to the memory. Note that the memory must
|
||||
// be de-allocated using AlignedFree.
|
||||
void* AlignedMalloc(size_t size, size_t alignment);
|
||||
// De-allocates memory created using the AlignedMalloc() API.
|
||||
void AlignedFree(void* mem_block);
|
||||
|
||||
// Templated versions to facilitate usage of aligned malloc without casting
|
||||
// to and from void*.
|
||||
template<typename T>
|
||||
T* GetRightAlign(const T* ptr, size_t alignment) {
|
||||
return reinterpret_cast<T*>(GetRightAlign(reinterpret_cast<const void*>(ptr),
|
||||
alignment));
|
||||
}
|
||||
template<typename T>
|
||||
T* AlignedMalloc(size_t size, size_t alignment) {
|
||||
return reinterpret_cast<T*>(AlignedMalloc(size, alignment));
|
||||
}
|
||||
|
||||
// Deleter for use with scoped_ptr. E.g., use as
|
||||
// scoped_ptr<Foo, AlignedFreeDeleter> foo;
|
||||
struct AlignedFreeDeleter {
|
||||
inline void operator()(void* ptr) const {
|
||||
AlignedFree(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
24
webrtc/system_wrappers/interface/compile_assert_c.h
Normal file
24
webrtc/system_wrappers/interface/compile_assert_c.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#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_
|
70
webrtc/system_wrappers/interface/event_wrapper.h
Normal file
70
webrtc/system_wrappers/interface/event_wrapper.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_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_
|
78
webrtc/system_wrappers/interface/file_wrapper.h
Normal file
78
webrtc/system_wrappers/interface/file_wrapper.h
Normal 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_
|
161
webrtc/system_wrappers/interface/logging.h
Normal file
161
webrtc/system_wrappers/interface/logging.h
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This is a highly stripped-down version of libjingle's talk/base/logging.h.
|
||||
// It is a thin wrapper around WEBRTC_TRACE, maintaining the libjingle log
|
||||
// semantics to ease a transition to that format.
|
||||
|
||||
// NOTE: LS_INFO maps to a new trace level which should be reserved for
|
||||
// infrequent, non-verbose logs. The other levels below kTraceWarning have been
|
||||
// rendered essentially useless due to their verbosity. Carefully consider the
|
||||
// impact of adding a new LS_INFO log. If it will be logged at anything
|
||||
// approaching a frame or packet frequency, use LS_VERBOSE if necessary, or
|
||||
// preferably, do not log at all.
|
||||
|
||||
// LOG(...) an ostream target that can be used to send formatted
|
||||
// output to a variety of logging targets, such as debugger console, stderr,
|
||||
// file, or any StreamInterface.
|
||||
// The severity level passed as the first argument to the LOGging
|
||||
// functions is used as a filter, to limit the verbosity of the logging.
|
||||
// Static members of LogMessage documented below are used to control the
|
||||
// verbosity and target of the output.
|
||||
// There are several variations on the LOG macro which facilitate logging
|
||||
// of common error conditions, detailed below.
|
||||
|
||||
// LOG(sev) logs the given stream at severity "sev", which must be a
|
||||
// compile-time constant of the LoggingSeverity type, without the namespace
|
||||
// prefix.
|
||||
// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
|
||||
// type (basically, it just doesn't prepend the namespace).
|
||||
// LOG_F(sev) Like LOG(), but includes the name of the current function.
|
||||
|
||||
// Additional helper macros added by WebRTC:
|
||||
// LOG_API is a shortcut for API call logging. Pass in the input parameters of
|
||||
// the method. For example:
|
||||
// Foo(int bar, int baz) {
|
||||
// LOG_API2(bar, baz);
|
||||
// }
|
||||
//
|
||||
// LOG_FERR is a shortcut for logging a failed function call. For example:
|
||||
// if (!Foo(bar)) {
|
||||
// LOG_FERR1(LS_WARNING, Foo, bar);
|
||||
// }
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note that the non-standard LoggingSeverity aliases exist because they are
|
||||
// still in broad use. The meanings of the levels are:
|
||||
// LS_SENSITIVE: Information which should only be logged with the consent
|
||||
// of the user, due to privacy concerns.
|
||||
// LS_VERBOSE: This level is for data which we do not want to appear in the
|
||||
// normal debug log, but should appear in diagnostic logs.
|
||||
// LS_INFO: Chatty level used in debugging for all sorts of things, the default
|
||||
// in debug builds.
|
||||
// LS_WARNING: Something that may warrant investigation.
|
||||
// LS_ERROR: Something that should not have occurred.
|
||||
enum LoggingSeverity {
|
||||
LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR
|
||||
};
|
||||
|
||||
class LogMessage {
|
||||
public:
|
||||
LogMessage(const char* file, int line, LoggingSeverity sev);
|
||||
~LogMessage();
|
||||
|
||||
static bool Loggable(LoggingSeverity sev);
|
||||
std::ostream& stream() { return print_stream_; }
|
||||
|
||||
private:
|
||||
// The ostream that buffers the formatted message before output
|
||||
std::ostringstream print_stream_;
|
||||
|
||||
// The severity level of this message
|
||||
LoggingSeverity severity_;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Macros which automatically disable logging when WEBRTC_LOGGING == 0
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOG
|
||||
// The following non-obvious technique for implementation of a
|
||||
// conditional log stream was stolen from google3/base/logging.h.
|
||||
|
||||
// This class is used to explicitly ignore values in the conditional
|
||||
// logging macros. This avoids compiler warnings like "value computed
|
||||
// is not used" and "statement has no effect".
|
||||
|
||||
class LogMessageVoidify {
|
||||
public:
|
||||
LogMessageVoidify() { }
|
||||
// This has to be an operator with a precedence lower than << but
|
||||
// higher than ?:
|
||||
void operator&(std::ostream&) { }
|
||||
};
|
||||
|
||||
#if defined(WEBRTC_RESTRICT_LOGGING)
|
||||
// This should compile away logs matching the following condition.
|
||||
#define RESTRICT_LOGGING_PRECONDITION(sev) \
|
||||
sev < webrtc::LS_INFO ? (void) 0 :
|
||||
#else
|
||||
#define RESTRICT_LOGGING_PRECONDITION(sev)
|
||||
#endif
|
||||
|
||||
#define LOG_SEVERITY_PRECONDITION(sev) \
|
||||
RESTRICT_LOGGING_PRECONDITION(sev) !(webrtc::LogMessage::Loggable(sev)) \
|
||||
? (void) 0 \
|
||||
: webrtc::LogMessageVoidify() &
|
||||
|
||||
#define LOG(sev) \
|
||||
LOG_SEVERITY_PRECONDITION(webrtc::sev) \
|
||||
webrtc::LogMessage(__FILE__, __LINE__, webrtc::sev).stream()
|
||||
|
||||
// The _V version is for when a variable is passed in. It doesn't do the
|
||||
// namespace concatination.
|
||||
#define LOG_V(sev) \
|
||||
LOG_SEVERITY_PRECONDITION(sev) \
|
||||
webrtc::LogMessage(__FILE__, __LINE__, sev).stream()
|
||||
|
||||
// The _F version prefixes the message with the current function name.
|
||||
#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F)
|
||||
#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
|
||||
#else
|
||||
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
|
||||
#endif
|
||||
|
||||
#define LOG_API0() LOG_F(LS_VERBOSE)
|
||||
#define LOG_API1(v1) LOG_API0() << #v1 << "=" << v1
|
||||
#define LOG_API2(v1, v2) LOG_API1(v1) \
|
||||
<< ", " << #v2 << "=" << v2
|
||||
#define LOG_API3(v1, v2, v3) LOG_API2(v1, v2) \
|
||||
<< ", " << #v3 << "=" << v3
|
||||
|
||||
#define LOG_FERR0(sev, func) LOG(sev) << #func << " failed"
|
||||
#define LOG_FERR1(sev, func, v1) LOG_FERR0(sev, func) \
|
||||
<< ": " << #v1 << "=" << v1
|
||||
#define LOG_FERR2(sev, func, v1, v2) LOG_FERR1(sev, func, v1) \
|
||||
<< ", " << #v2 << "=" << v2
|
||||
#define LOG_FERR3(sev, func, v1, v2, v3) LOG_FERR2(sev, func, v1, v2) \
|
||||
<< ", " << #v3 << "=" << v3
|
||||
#define LOG_FERR4(sev, func, v1, v2, v3, v4) LOG_FERR3(sev, func, v1, v2, v3) \
|
||||
<< ", " << #v4 << "=" << v4
|
||||
|
||||
#endif // LOG
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGGING_H_
|
136
webrtc/system_wrappers/interface/metrics.h
Normal file
136
webrtc/system_wrappers/interface/metrics.h
Normal 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_
|
||||
|
68
webrtc/system_wrappers/interface/rw_lock_wrapper.h
Normal file
68
webrtc/system_wrappers/interface/rw_lock_wrapper.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
|
||||
#include "webrtc/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_
|
157
webrtc/system_wrappers/interface/scoped_vector.h
Normal file
157
webrtc/system_wrappers/interface/scoped_vector.h
Normal 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_
|
24
webrtc/system_wrappers/interface/sleep.h
Normal file
24
webrtc/system_wrappers/interface/sleep.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This function sleeps for the specified number of milliseconds.
|
||||
// It may return early if the thread is woken by some other event,
|
||||
// such as the delivery of a signal on Unix.
|
||||
void SleepMs(int msecs);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
|
153
webrtc/system_wrappers/interface/static_instance.h
Normal file
153
webrtc/system_wrappers/interface/static_instance.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum CountOperation {
|
||||
kRelease,
|
||||
kAddRef,
|
||||
kAddRefNoCreate
|
||||
};
|
||||
enum CreateOperation {
|
||||
kInstanceExists,
|
||||
kCreate,
|
||||
kDestroy
|
||||
};
|
||||
|
||||
template <class T>
|
||||
// Construct On First Use idiom. Avoids
|
||||
// "static initialization order fiasco".
|
||||
static T* GetStaticInstance(CountOperation count_operation) {
|
||||
// TODO (hellner): use atomic wrapper instead.
|
||||
static volatile long instance_count = 0;
|
||||
static T* volatile instance = NULL;
|
||||
CreateOperation state = kInstanceExists;
|
||||
#ifndef _WIN32
|
||||
// This memory is staticly allocated once. The application does not try to
|
||||
// free this memory. This approach is taken to avoid issues with
|
||||
// destruction order for statically allocated memory. The memory will be
|
||||
// reclaimed by the OS and memory leak tools will not recognize memory
|
||||
// reachable from statics leaked so no noise is added by doing this.
|
||||
static CriticalSectionWrapper* crit_sect(
|
||||
CriticalSectionWrapper::CreateCriticalSection());
|
||||
CriticalSectionScoped lock(crit_sect);
|
||||
|
||||
if (count_operation ==
|
||||
kAddRefNoCreate && instance_count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (count_operation ==
|
||||
kAddRef ||
|
||||
count_operation == kAddRefNoCreate) {
|
||||
instance_count++;
|
||||
if (instance_count == 1) {
|
||||
state = kCreate;
|
||||
}
|
||||
} else {
|
||||
instance_count--;
|
||||
if (instance_count == 0) {
|
||||
state = kDestroy;
|
||||
}
|
||||
}
|
||||
if (state == kCreate) {
|
||||
instance = T::CreateInstance();
|
||||
} else if (state == kDestroy) {
|
||||
T* old_instance = instance;
|
||||
instance = NULL;
|
||||
// The state will not change past this point. Release the critical
|
||||
// section while deleting the object in case it would be blocking on
|
||||
// access back to this object. (This is the case for the tracing class
|
||||
// since the thread owned by the tracing class also traces).
|
||||
// TODO(hellner): this is a bit out of place but here goes, de-couple
|
||||
// thread implementation with trace implementation.
|
||||
crit_sect->Leave();
|
||||
if (old_instance) {
|
||||
delete old_instance;
|
||||
}
|
||||
// Re-acquire the lock since the scoped critical section will release
|
||||
// it.
|
||||
crit_sect->Enter();
|
||||
return NULL;
|
||||
}
|
||||
#else // _WIN32
|
||||
if (count_operation ==
|
||||
kAddRefNoCreate && instance_count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (count_operation == kAddRefNoCreate) {
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
// The instance has been destroyed by some other thread. Rollback.
|
||||
InterlockedDecrement(&instance_count);
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
// Sanity to catch corrupt state.
|
||||
if (instance == NULL) {
|
||||
assert(false);
|
||||
InterlockedDecrement(&instance_count);
|
||||
return NULL;
|
||||
}
|
||||
} else if (count_operation == kAddRef) {
|
||||
if (instance_count == 0) {
|
||||
state = kCreate;
|
||||
} else {
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
// InterlockedDecrement because reference count should not be
|
||||
// updated just yet (that's done when the instance is created).
|
||||
InterlockedDecrement(&instance_count);
|
||||
state = kCreate;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int new_value = InterlockedDecrement(&instance_count);
|
||||
if (new_value == 0) {
|
||||
state = kDestroy;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == kCreate) {
|
||||
// Create instance and let whichever thread finishes first assign its
|
||||
// local copy to the global instance. All other threads reclaim their
|
||||
// local copy.
|
||||
T* new_instance = T::CreateInstance();
|
||||
if (1 == InterlockedIncrement(&instance_count)) {
|
||||
InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&instance),
|
||||
new_instance);
|
||||
} else {
|
||||
InterlockedDecrement(&instance_count);
|
||||
if (new_instance) {
|
||||
delete static_cast<T*>(new_instance);
|
||||
}
|
||||
}
|
||||
} else if (state == kDestroy) {
|
||||
T* old_value = static_cast<T*>(InterlockedExchangePointer(
|
||||
reinterpret_cast<void * volatile*>(&instance), NULL));
|
||||
if (old_value) {
|
||||
delete static_cast<T*>(old_value);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif // #ifndef _WIN32
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namspace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STATIC_INSTANCE_H_
|
265
webrtc/system_wrappers/interface/stl_util.h
Normal file
265
webrtc/system_wrappers/interface/stl_util.h
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/stl_util.h.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Clears internal memory of an STL object.
|
||||
// STL clear()/reserve(0) does not always free internal memory allocated
|
||||
// This function uses swap/destructor to ensure the internal memory is freed.
|
||||
template<class T>
|
||||
void STLClearObject(T* obj) {
|
||||
T tmp;
|
||||
tmp.swap(*obj);
|
||||
// Sometimes "T tmp" allocates objects with memory (arena implementation?).
|
||||
// Hence using additional reserve(0) even if it doesn't always work.
|
||||
obj->reserve(0);
|
||||
}
|
||||
|
||||
// For a range within a container of pointers, calls delete (non-array version)
|
||||
// on these pointers.
|
||||
// NOTE: for these three functions, we could just implement a DeleteObject
|
||||
// functor and then call for_each() on the range and functor, but this
|
||||
// requires us to pull in all of algorithm.h, which seems expensive.
|
||||
// For hash_[multi]set, it is important that this deletes behind the iterator
|
||||
// because the hash_set may call the hash function on the iterator when it is
|
||||
// advanced, which could result in the hash function trying to deference a
|
||||
// stale pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete *temp;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete (non-array version) on
|
||||
// BOTH items in the pairs.
|
||||
// NOTE: Like STLDeleteContainerPointers, it is important that this deletes
|
||||
// behind the iterator because if both the key and value are deleted, the
|
||||
// container may call the hash function on the iterator when it is advanced,
|
||||
// which could result in the hash function trying to dereference a stale
|
||||
// pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->first;
|
||||
delete temp->second;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete (non-array version) on
|
||||
// the FIRST item in the pairs.
|
||||
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairFirstPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->first;
|
||||
}
|
||||
}
|
||||
|
||||
// For a range within a container of pairs, calls delete.
|
||||
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
|
||||
// Deleting the value does not always invalidate the iterator, but it may
|
||||
// do so if the key is a pointer into the value object.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete temp->second;
|
||||
}
|
||||
}
|
||||
|
||||
// To treat a possibly-empty vector as an array, use these functions.
|
||||
// If you know the array will never be empty, you can use &*v.begin()
|
||||
// directly, but that is undefined behaviour if |v| is empty.
|
||||
template<typename T>
|
||||
inline T* vector_as_array(std::vector<T>* v) {
|
||||
return v->empty() ? NULL : &*v->begin();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T* vector_as_array(const std::vector<T>* v) {
|
||||
return v->empty() ? NULL : &*v->begin();
|
||||
}
|
||||
|
||||
// Return a mutable char* pointing to a string's internal buffer,
|
||||
// which may not be null-terminated. Writing through this pointer will
|
||||
// modify the string.
|
||||
//
|
||||
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
|
||||
// next call to a string method that invalidates iterators.
|
||||
//
|
||||
// As of 2006-04, there is no standard-blessed way of getting a
|
||||
// mutable reference to a string's internal buffer. However, issue 530
|
||||
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
|
||||
// proposes this as the method. According to Matt Austern, this should
|
||||
// already work on all current implementations.
|
||||
inline char* string_as_array(std::string* str) {
|
||||
// DO NOT USE const_cast<char*>(str->data())
|
||||
return str->empty() ? NULL : &*str->begin();
|
||||
}
|
||||
|
||||
// The following functions are useful for cleaning up STL containers whose
|
||||
// elements point to allocated memory.
|
||||
|
||||
// STLDeleteElements() deletes all the elements in an STL container and clears
|
||||
// the container. This function is suitable for use with a vector, set,
|
||||
// hash_set, or any other STL container which defines sensible begin(), end(),
|
||||
// and clear() methods.
|
||||
//
|
||||
// If container is NULL, this function is a no-op.
|
||||
//
|
||||
// As an alternative to calling STLDeleteElements() directly, consider
|
||||
// STLElementDeleter (defined below), which ensures that your container's
|
||||
// elements are deleted when the STLElementDeleter goes out of scope.
|
||||
template <class T>
|
||||
void STLDeleteElements(T* container) {
|
||||
if (!container)
|
||||
return;
|
||||
STLDeleteContainerPointers(container->begin(), container->end());
|
||||
container->clear();
|
||||
}
|
||||
|
||||
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
|
||||
// deletes all the "value" components and clears the container. Does nothing
|
||||
// in the case it's given a NULL pointer.
|
||||
template <class T>
|
||||
void STLDeleteValues(T* container) {
|
||||
if (!container)
|
||||
return;
|
||||
for (typename T::iterator i(container->begin()); i != container->end(); ++i)
|
||||
delete i->second;
|
||||
container->clear();
|
||||
}
|
||||
|
||||
|
||||
// The following classes provide a convenient way to delete all elements or
|
||||
// values from STL containers when they goes out of scope. This greatly
|
||||
// simplifies code that creates temporary objects and has multiple return
|
||||
// statements. Example:
|
||||
//
|
||||
// vector<MyProto *> tmp_proto;
|
||||
// STLElementDeleter<vector<MyProto *> > d(&tmp_proto);
|
||||
// if (...) return false;
|
||||
// ...
|
||||
// return success;
|
||||
|
||||
// Given a pointer to an STL container this class will delete all the element
|
||||
// pointers when it goes out of scope.
|
||||
template<class T>
|
||||
class STLElementDeleter {
|
||||
public:
|
||||
STLElementDeleter<T>(T* container) : container_(container) {}
|
||||
~STLElementDeleter<T>() { STLDeleteElements(container_); }
|
||||
|
||||
private:
|
||||
T* container_;
|
||||
};
|
||||
|
||||
// Given a pointer to an STL container this class will delete all the value
|
||||
// pointers when it goes out of scope.
|
||||
template<class T>
|
||||
class STLValueDeleter {
|
||||
public:
|
||||
STLValueDeleter<T>(T* container) : container_(container) {}
|
||||
~STLValueDeleter<T>() { STLDeleteValues(container_); }
|
||||
|
||||
private:
|
||||
T* container_;
|
||||
};
|
||||
|
||||
// Test to see if a set, map, hash_set or hash_map contains a particular key.
|
||||
// Returns true if the key is in the collection.
|
||||
template <typename Collection, typename Key>
|
||||
bool ContainsKey(const Collection& collection, const Key& key) {
|
||||
return collection.find(key) != collection.end();
|
||||
}
|
||||
|
||||
// Returns true if the container is sorted.
|
||||
template <typename Container>
|
||||
bool STLIsSorted(const Container& cont) {
|
||||
// Note: Use reverse iterator on container to ensure we only require
|
||||
// value_type to implement operator<.
|
||||
return std::adjacent_find(cont.rbegin(), cont.rend(),
|
||||
std::less<typename Container::value_type>())
|
||||
== cont.rend();
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the difference of two sorted containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType difference;
|
||||
std::set_difference(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(difference, difference.end()));
|
||||
return difference;
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the union of two sorted containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType result;
|
||||
std::set_union(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(result, result.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a new ResultType containing the intersection of two sorted
|
||||
// containers.
|
||||
template <typename ResultType, typename Arg1, typename Arg2>
|
||||
ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
ResultType result;
|
||||
std::set_intersection(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end(),
|
||||
std::inserter(result, result.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns true if the sorted container |a1| contains all elements of the sorted
|
||||
// container |a2|.
|
||||
template <typename Arg1, typename Arg2>
|
||||
bool STLIncludes(const Arg1& a1, const Arg2& a2) {
|
||||
assert(STLIsSorted(a1));
|
||||
assert(STLIsSorted(a2));
|
||||
return std::includes(a1.begin(), a1.end(),
|
||||
a2.begin(), a2.end());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_STL_UTIL_H_
|
95
webrtc/system_wrappers/interface/thread_wrapper.h
Normal file
95
webrtc/system_wrappers/interface/thread_wrapper.h
Normal 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_
|
92
webrtc/system_wrappers/interface/trace.h
Normal file
92
webrtc/system_wrappers/interface/trace.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*
|
||||
* System independent wrapper for logging runtime information to file.
|
||||
* Note: All log messages will be written to the same trace file.
|
||||
* Note: If too many messages are written to file there will be a build up of
|
||||
* messages. Apply filtering to avoid that.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if defined(WEBRTC_RESTRICT_LOGGING)
|
||||
// Disable all TRACE macros. The LOG macro is still functional.
|
||||
#define WEBRTC_TRACE true ? (void) 0 : Trace::Add
|
||||
#else
|
||||
#define WEBRTC_TRACE Trace::Add
|
||||
#endif
|
||||
|
||||
class Trace {
|
||||
public:
|
||||
// The length of the trace text preceeding the log message.
|
||||
static const int kBoilerplateLength;
|
||||
// The position of the timestamp text within a trace.
|
||||
static const int kTimestampPosition;
|
||||
// The length of the timestamp (without "delta" field).
|
||||
static const int kTimestampLength;
|
||||
|
||||
// Increments the reference count to the trace.
|
||||
static void CreateTrace();
|
||||
// Decrements the reference count to the trace.
|
||||
static void ReturnTrace();
|
||||
// Note: any instance that writes to the trace file should increment and
|
||||
// decrement the reference count on construction and destruction,
|
||||
// respectively.
|
||||
|
||||
// Specifies what type of messages should be written to the trace file. The
|
||||
// filter parameter is a bitmask where each message type is enumerated by the
|
||||
// TraceLevel enumerator. TODO(hellner): why is the TraceLevel enumerator not
|
||||
// defined in this file?
|
||||
static void set_level_filter(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_
|
100
webrtc/system_wrappers/source/aligned_malloc.cc
Normal file
100
webrtc/system_wrappers/source/aligned_malloc.cc
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/aligned_malloc.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Reference on memory alignment:
|
||||
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
|
||||
namespace webrtc {
|
||||
|
||||
uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
|
||||
// The pointer should be aligned with |alignment| bytes. The - 1 guarantees
|
||||
// that it is aligned towards the closest higher (right) address.
|
||||
return (start_pos + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Alignment must be an integer power of two.
|
||||
bool ValidAlignment(size_t alignment) {
|
||||
if (!alignment) {
|
||||
return false;
|
||||
}
|
||||
return (alignment & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
void* GetRightAlign(const void* pointer, size_t alignment) {
|
||||
if (!pointer) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
|
||||
return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
|
||||
}
|
||||
|
||||
void* AlignedMalloc(size_t size, size_t alignment) {
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The memory is aligned towards the lowest address that so only
|
||||
// alignment - 1 bytes needs to be allocated.
|
||||
// A pointer to the start of the memory must be stored so that it can be
|
||||
// retreived for deletion, ergo the sizeof(uintptr_t).
|
||||
void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
|
||||
if (memory_pointer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Aligning after the sizeof(uintptr_t) bytes will leave room for the header
|
||||
// in the same memory block.
|
||||
uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
align_start_pos += sizeof(uintptr_t);
|
||||
uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
|
||||
void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
|
||||
|
||||
// Store the address to the beginning of the memory just before the aligned
|
||||
// memory.
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
void* header_pointer = reinterpret_cast<void*>(header_pos);
|
||||
uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
|
||||
|
||||
return aligned_pointer;
|
||||
}
|
||||
|
||||
void AlignedFree(void* mem_block) {
|
||||
if (mem_block == NULL) {
|
||||
return;
|
||||
}
|
||||
uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
|
||||
// Read out the address of the AlignedMemory struct from the header.
|
||||
uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
|
||||
void* memory_start = reinterpret_cast<void*>(memory_start_pos);
|
||||
free(memory_start);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
54
webrtc/system_wrappers/source/event.cc
Normal file
54
webrtc/system_wrappers/source/event.cc
Normal 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
|
231
webrtc/system_wrappers/source/event_timer_posix.cc
Normal file
231
webrtc/system_wrappers/source/event_timer_posix.cc
Normal 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
|
60
webrtc/system_wrappers/source/event_timer_posix.h
Normal file
60
webrtc/system_wrappers/source/event_timer_posix.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_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_
|
78
webrtc/system_wrappers/source/event_timer_win.cc
Normal file
78
webrtc/system_wrappers/source/event_timer_win.cc
Normal 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
|
40
webrtc/system_wrappers/source/event_timer_win.h
Normal file
40
webrtc/system_wrappers/source/event_timer_win.h
Normal 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_
|
278
webrtc/system_wrappers/source/file_impl.cc
Normal file
278
webrtc/system_wrappers/source/file_impl.cc
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/file_impl.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/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
|
69
webrtc/system_wrappers/source/file_impl.h
Normal file
69
webrtc/system_wrappers/source/file_impl.h
Normal 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_
|
62
webrtc/system_wrappers/source/logging.cc
Normal file
62
webrtc/system_wrappers/source/logging.cc
Normal 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
|
29
webrtc/system_wrappers/source/metrics_default.cc
Normal file
29
webrtc/system_wrappers/source/metrics_default.cc
Normal 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
|
||||
|
77
webrtc/system_wrappers/source/rw_lock_generic.cc
Normal file
77
webrtc/system_wrappers/source/rw_lock_generic.cc
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockGeneric::RWLockGeneric()
|
||||
: readers_active_(0),
|
||||
writer_active_(false),
|
||||
readers_waiting_(0),
|
||||
writers_waiting_(0) {
|
||||
critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
}
|
||||
|
||||
RWLockGeneric::~RWLockGeneric() {
|
||||
delete write_condition_;
|
||||
delete read_condition_;
|
||||
delete critical_section_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || readers_active_ > 0) {
|
||||
++writers_waiting_;
|
||||
while (writer_active_ || readers_active_ > 0) {
|
||||
write_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--writers_waiting_;
|
||||
}
|
||||
writer_active_ = true;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
writer_active_ = false;
|
||||
if (writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
} else if (readers_waiting_ > 0) {
|
||||
read_condition_->WakeAll();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || writers_waiting_ > 0) {
|
||||
++readers_waiting_;
|
||||
|
||||
while (writer_active_ || writers_waiting_ > 0) {
|
||||
read_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--readers_waiting_;
|
||||
}
|
||||
++readers_active_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
--readers_active_;
|
||||
if (readers_active_ == 0 && writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
46
webrtc/system_wrappers/source/rw_lock_generic.h
Normal file
46
webrtc/system_wrappers/source/rw_lock_generic.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
class RWLockGeneric : public RWLockWrapper {
|
||||
public:
|
||||
RWLockGeneric();
|
||||
~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_
|
51
webrtc/system_wrappers/source/rw_lock_posix.cc
Normal file
51
webrtc/system_wrappers/source/rw_lock_posix.cc
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockPosix::RWLockPosix() : lock_() {
|
||||
}
|
||||
|
||||
RWLockPosix::~RWLockPosix() {
|
||||
pthread_rwlock_destroy(&lock_);
|
||||
}
|
||||
|
||||
RWLockPosix* RWLockPosix::Create() {
|
||||
RWLockPosix* ret_val = new RWLockPosix();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool RWLockPosix::Init() {
|
||||
return pthread_rwlock_init(&lock_, 0) == 0;
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockExclusive() {
|
||||
pthread_rwlock_wrlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockExclusive() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockShared() {
|
||||
pthread_rwlock_rdlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockShared() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
webrtc/system_wrappers/source/rw_lock_posix.h
Normal file
41
webrtc/system_wrappers/source/rw_lock_posix.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockPosix : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockPosix* Create();
|
||||
~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_
|
97
webrtc/system_wrappers/source/rw_lock_win.cc
Normal file
97
webrtc/system_wrappers/source/rw_lock_win.cc
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_win.h"
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static bool native_rw_locks_supported = false;
|
||||
static bool module_load_attempted = false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
typedef void (WINAPI* InitializeSRWLock)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockExclusive)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockExclusive)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockShared)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockShared)(PSRWLOCK);
|
||||
|
||||
InitializeSRWLock initialize_srw_lock;
|
||||
AcquireSRWLockExclusive acquire_srw_lock_exclusive;
|
||||
AcquireSRWLockShared acquire_srw_lock_shared;
|
||||
ReleaseSRWLockShared release_srw_lock_shared;
|
||||
ReleaseSRWLockExclusive release_srw_lock_exclusive;
|
||||
|
||||
RWLockWin::RWLockWin() {
|
||||
initialize_srw_lock(&lock_);
|
||||
}
|
||||
|
||||
RWLockWin* RWLockWin::Create() {
|
||||
if (!LoadModule()) {
|
||||
return NULL;
|
||||
}
|
||||
return new RWLockWin();
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockExclusive() {
|
||||
acquire_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockExclusive() {
|
||||
release_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockShared() {
|
||||
acquire_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockShared() {
|
||||
release_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
bool RWLockWin::LoadModule() {
|
||||
if (module_load_attempted) {
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
module_load_attempted = true;
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if (!library) {
|
||||
return false;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
initialize_srw_lock =
|
||||
(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");
|
||||
|
||||
acquire_srw_lock_exclusive =
|
||||
(AcquireSRWLockExclusive)GetProcAddress(library,
|
||||
"AcquireSRWLockExclusive");
|
||||
release_srw_lock_exclusive =
|
||||
(ReleaseSRWLockExclusive)GetProcAddress(library,
|
||||
"ReleaseSRWLockExclusive");
|
||||
acquire_srw_lock_shared =
|
||||
(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
|
||||
release_srw_lock_shared =
|
||||
(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");
|
||||
|
||||
if (initialize_srw_lock && acquire_srw_lock_exclusive &&
|
||||
release_srw_lock_exclusive && acquire_srw_lock_shared &&
|
||||
release_srw_lock_shared) {
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Native RW Lock");
|
||||
native_rw_locks_supported = true;
|
||||
}
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
40
webrtc/system_wrappers/source/rw_lock_win.h
Normal file
40
webrtc/system_wrappers/source/rw_lock_win.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWin : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockWin* Create();
|
||||
~RWLockWin() {}
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
private:
|
||||
RWLockWin();
|
||||
static bool LoadModule();
|
||||
|
||||
SRWLOCK lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
36
webrtc/system_wrappers/source/sleep.cc
Normal file
36
webrtc/system_wrappers/source/sleep.cc
Normal 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
|
33
webrtc/system_wrappers/source/thread.cc
Normal file
33
webrtc/system_wrappers/source/thread.cc
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/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
|
166
webrtc/system_wrappers/source/thread_posix.cc
Normal file
166
webrtc/system_wrappers/source/thread_posix.cc
Normal 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, ¶m) != 0) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceError, kTraceUtility, -1, "unable to set thread priority");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
|
||||
}
|
||||
|
||||
void ThreadPosix::Run() {
|
||||
if (!name_.empty()) {
|
||||
// Setting the thread name may fail (harmlessly) if running inside a
|
||||
// sandbox. Ignore failures if they happen.
|
||||
rtc::SetCurrentThreadName(name_.substr(0, 63).c_str());
|
||||
}
|
||||
|
||||
// It's a requirement that for successful thread creation that the run
|
||||
// function be called at least once (see RunFunctionIsCalled unit test),
|
||||
// so to fullfill that requirement, we use a |do| loop and not |while|.
|
||||
do {
|
||||
if (!run_function_(obj_))
|
||||
break;
|
||||
} while (!stop_event_.Wait(0));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
53
webrtc/system_wrappers/source/thread_posix.h
Normal file
53
webrtc/system_wrappers/source/thread_posix.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#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_
|
107
webrtc/system_wrappers/source/thread_win.cc
Normal file
107
webrtc/system_wrappers/source/thread_win.cc
Normal 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
|
48
webrtc/system_wrappers/source/thread_win.h
Normal file
48
webrtc/system_wrappers/source/thread_win.h
Normal 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_
|
604
webrtc/system_wrappers/source/trace_impl.cc
Normal file
604
webrtc/system_wrappers/source/trace_impl.cc
Normal 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
|
106
webrtc/system_wrappers/source/trace_impl.h
Normal file
106
webrtc/system_wrappers/source/trace_impl.h
Normal 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_
|
90
webrtc/system_wrappers/source/trace_posix.cc
Normal file
90
webrtc/system_wrappers/source/trace_posix.cc
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#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
|
39
webrtc/system_wrappers/source/trace_posix.h
Normal file
39
webrtc/system_wrappers/source/trace_posix.h
Normal 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_
|
97
webrtc/system_wrappers/source/trace_win.cc
Normal file
97
webrtc/system_wrappers/source/trace_win.cc
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/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
|
36
webrtc/system_wrappers/source/trace_win.h
Normal file
36
webrtc/system_wrappers/source/trace_win.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TraceWindows : public TraceImpl {
|
||||
public:
|
||||
TraceWindows();
|
||||
virtual ~TraceWindows();
|
||||
|
||||
virtual int32_t AddTime(char* trace_message, const TraceLevel level) const;
|
||||
|
||||
virtual int32_t AddDateTimeInfo(char* trace_message) const;
|
||||
private:
|
||||
volatile mutable uint32_t prev_api_tick_count_;
|
||||
volatile mutable uint32_t prev_tick_count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
Reference in New Issue
Block a user