Update to current webrtc library
This is from the upstream library commit id 3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium 88.0.4290.1.
This commit is contained in:
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Reference on memory alignment:
|
||||
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
|
||||
namespace webrtc {
|
||||
|
||||
uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
|
||||
// The pointer should be aligned with |alignment| bytes. The - 1 guarantees
|
||||
// that it is aligned towards the closest higher (right) address.
|
||||
return (start_pos + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Alignment must be an integer power of two.
|
||||
bool ValidAlignment(size_t alignment) {
|
||||
if (!alignment) {
|
||||
return false;
|
||||
}
|
||||
return (alignment & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
void* GetRightAlign(const void* pointer, size_t alignment) {
|
||||
if (!pointer) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
|
||||
return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
|
||||
}
|
||||
|
||||
void* AlignedMalloc(size_t size, size_t alignment) {
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!ValidAlignment(alignment)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The memory is aligned towards the lowest address that so only
|
||||
// alignment - 1 bytes needs to be allocated.
|
||||
// A pointer to the start of the memory must be stored so that it can be
|
||||
// retreived for deletion, ergo the sizeof(uintptr_t).
|
||||
void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
|
||||
if (memory_pointer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Aligning after the sizeof(uintptr_t) bytes will leave room for the header
|
||||
// in the same memory block.
|
||||
uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
align_start_pos += sizeof(uintptr_t);
|
||||
uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
|
||||
void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
|
||||
|
||||
// Store the address to the beginning of the memory just before the aligned
|
||||
// memory.
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
void* header_pointer = reinterpret_cast<void*>(header_pos);
|
||||
uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
|
||||
memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
|
||||
|
||||
return aligned_pointer;
|
||||
}
|
||||
|
||||
void AlignedFree(void* mem_block) {
|
||||
if (mem_block == NULL) {
|
||||
return;
|
||||
}
|
||||
uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
|
||||
uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
|
||||
|
||||
// Read out the address of the AlignedMemory struct from the header.
|
||||
uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
|
||||
void* memory_start = reinterpret_cast<void*>(memory_start_pos);
|
||||
free(memory_start);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/condition_variable_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/condition_variable_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableWrapper::CreateConditionVariable() {
|
||||
#if defined(_WIN32)
|
||||
// Try to create native condition variable implementation.
|
||||
ConditionVariableWrapper* ret_val = ConditionVariableNativeWin::Create();
|
||||
if (!ret_val) {
|
||||
// Native condition variable implementation does not exist. Create generic
|
||||
// condition variable based on events.
|
||||
ret_val = new ConditionVariableEventWin();
|
||||
}
|
||||
return ret_val;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
return ConditionVariablePosix::Create();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
Source:
|
||||
http://www1.cse.wustl.edu/~schmidt/ACE-copying.html
|
||||
|
||||
License:
|
||||
Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM),
|
||||
and CoSMIC(TM)
|
||||
|
||||
ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to
|
||||
as "DOC software") are copyrighted by Douglas C. Schmidt and his research
|
||||
group at Washington University, University of California, Irvine, and
|
||||
Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC
|
||||
software is open-source, freely available software, you are free to use,
|
||||
modify, copy, and distribute--perpetually and irrevocably--the DOC software
|
||||
source code and object code produced from the source, as well as copy and
|
||||
distribute modified versions of this software. You must, however, include this
|
||||
copyright statement along with any code built using DOC software that you
|
||||
release. No copyright statement needs to be provided if you just ship binary
|
||||
executables of your software products.
|
||||
You can use DOC software in commercial and/or binary software releases and are
|
||||
under no obligation to redistribute any of your source code that is built
|
||||
using DOC software. Note, however, that you may not misappropriate the DOC
|
||||
software code, such as copyrighting it yourself or claiming authorship of the
|
||||
DOC software code, in a way that will prevent DOC software from being
|
||||
distributed freely using an open-source development model. You needn't inform
|
||||
anyone that you're using DOC software in your software, though we encourage
|
||||
you to let us know so we can promote your project in the DOC software success
|
||||
stories.
|
||||
|
||||
The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC
|
||||
Group at the Institute for Software Integrated Systems (ISIS) and the Center
|
||||
for Distributed Object Computing of Washington University, St. Louis for the
|
||||
development of open-source software as part of the open-source software
|
||||
community. Submissions are provided by the submitter ``as is'' with no
|
||||
warranties whatsoever, including any warranty of merchantability,
|
||||
noninfringement of third party intellectual property, or fitness for any
|
||||
particular purpose. In no event shall the submitter be liable for any direct,
|
||||
indirect, special, exemplary, punitive, or consequential damages, including
|
||||
without limitation, lost profits, even if advised of the possibility of such
|
||||
damages. Likewise, DOC software is provided as is with no warranties of any
|
||||
kind, including the warranties of design, merchantability, and fitness for a
|
||||
particular purpose, noninfringement, or arising from a course of dealing,
|
||||
usage or trade practice. Washington University, UC Irvine, Vanderbilt
|
||||
University, their employees, and students shall have no liability with respect
|
||||
to the infringement of copyrights, trade secrets or any patents by DOC
|
||||
software or any part thereof. Moreover, in no event will Washington
|
||||
University, UC Irvine, or Vanderbilt University, their employees, or students
|
||||
be liable for any lost revenue or profits or other special, indirect and
|
||||
consequential damages.
|
||||
|
||||
DOC software is provided with no support and without any obligation on the
|
||||
part of Washington University, UC Irvine, Vanderbilt University, their
|
||||
employees, or students to assist in its use, correction, modification, or
|
||||
enhancement. A number of companies around the world provide commercial support
|
||||
for DOC software, however. DOC software is Y2K-compliant, as long as the
|
||||
underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant
|
||||
with the new US daylight savings rule passed by Congress as "The Energy Policy
|
||||
Act of 2005," which established new daylight savings times (DST) rules for the
|
||||
United States that expand DST as of March 2007. Since DOC software obtains
|
||||
time/date and calendaring information from operating systems users will not be
|
||||
affected by the new DST rules as long as they upgrade their operating systems
|
||||
accordingly.
|
||||
|
||||
The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington
|
||||
University, UC Irvine, and Vanderbilt University, may not be used to endorse
|
||||
or promote products or services derived from this source without express
|
||||
written permission from Washington University, UC Irvine, or Vanderbilt
|
||||
University. This license grants no permission to call products or services
|
||||
derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM),
|
||||
nor does it grant permission for the name Washington University, UC Irvine, or
|
||||
Vanderbilt University to appear in their names.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This source code contain modifications to the original source code
|
||||
* which can be found here:
|
||||
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
|
||||
* Modifications:
|
||||
* 1) Dynamic detection of native support for condition variables.
|
||||
* 2) Use of WebRTC defined types and classes. Renaming of some functions.
|
||||
* 3) Introduction of a second event for wake all functionality. This prevents
|
||||
* a thread from spinning on the same condition variable, preventing other
|
||||
* threads from waking up.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/condition_variable_event_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ConditionVariableEventWin::ConditionVariableEventWin() : eventID_(WAKEALL_0) {
|
||||
memset(&num_waiters_[0], 0, sizeof(num_waiters_));
|
||||
|
||||
InitializeCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
|
||||
TRUE, // manual-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
|
||||
events_[WAKE] = CreateEvent(NULL, // no security attributes
|
||||
FALSE, // auto-reset, sticky event
|
||||
FALSE, // initial state non-signaled
|
||||
NULL); // no name for event
|
||||
}
|
||||
|
||||
ConditionVariableEventWin::~ConditionVariableEventWin() {
|
||||
CloseHandle(events_[WAKE]);
|
||||
CloseHandle(events_[WAKEALL_1]);
|
||||
CloseHandle(events_[WAKEALL_0]);
|
||||
|
||||
DeleteCriticalSection(&num_waiters_crit_sect_);
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Get the eventID for the event that will be triggered by next
|
||||
// WakeAll() call and start waiting for it.
|
||||
const EventWakeUpType eventID =
|
||||
(WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
++(num_waiters_[eventID]);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&crit_sect);
|
||||
LeaveCriticalSection(&cs->crit);
|
||||
HANDLE events[2];
|
||||
events[0] = events_[WAKE];
|
||||
events[1] = events_[eventID];
|
||||
const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
|
||||
events,
|
||||
FALSE, // Wait for either.
|
||||
max_time_in_ms);
|
||||
|
||||
const bool ret_val = (result != WAIT_TIMEOUT);
|
||||
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
--(num_waiters_[eventID]);
|
||||
|
||||
// Last waiter should only be true for WakeAll(). WakeAll() correspond
|
||||
// to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
|
||||
const bool last_waiter = (result == WAIT_OBJECT_0 + 1) &&
|
||||
(num_waiters_[eventID] == 0);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (last_waiter) {
|
||||
// Reset/unset the WakeAll() event since all threads have been
|
||||
// released.
|
||||
ResetEvent(events_[eventID]);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&cs->crit);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::Wake() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
const bool have_waiters = (num_waiters_[WAKEALL_0] > 0) ||
|
||||
(num_waiters_[WAKEALL_1] > 0);
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[WAKE]);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableEventWin::WakeAll() {
|
||||
EnterCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
// Update current WakeAll() event
|
||||
eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
|
||||
|
||||
// Trigger current event
|
||||
const EventWakeUpType eventID = eventID_;
|
||||
const bool have_waiters = num_waiters_[eventID] > 0;
|
||||
LeaveCriticalSection(&num_waiters_crit_sect_);
|
||||
|
||||
if (have_waiters) {
|
||||
SetEvent(events_[eventID]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ConditionVariableEventWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
ConditionVariableEventWin();
|
||||
virtual ~ConditionVariableEventWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
enum EventWakeUpType {
|
||||
WAKEALL_0 = 0,
|
||||
WAKEALL_1 = 1,
|
||||
WAKE = 2,
|
||||
EVENT_COUNT = 3
|
||||
};
|
||||
|
||||
unsigned int num_waiters_[2];
|
||||
EventWakeUpType eventID_;
|
||||
CRITICAL_SECTION num_waiters_crit_sect_;
|
||||
HANDLE events_[EVENT_COUNT];
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static HMODULE library = NULL;
|
||||
static bool win_support_condition_variables_primitive = false;
|
||||
|
||||
PInitializeConditionVariable PInitializeConditionVariable_;
|
||||
PSleepConditionVariableCS PSleepConditionVariableCS_;
|
||||
PWakeConditionVariable PWakeConditionVariable_;
|
||||
PWakeAllConditionVariable PWakeAllConditionVariable_;
|
||||
|
||||
typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
ConditionVariableNativeWin::ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableNativeWin::~ConditionVariableNativeWin() {
|
||||
}
|
||||
|
||||
ConditionVariableWrapper* ConditionVariableNativeWin::Create() {
|
||||
ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::Init() {
|
||||
if (!library) {
|
||||
// Native implementation is supported on Vista+.
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
// TODO(henrike): this code results in an attempt to load the above dll
|
||||
// every time the previous attempt failed. Only try to load once.
|
||||
if (library) {
|
||||
// TODO(henrike): not thread safe as reading and writing to library is not
|
||||
// serialized. Fix.
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
PInitializeConditionVariable_ =
|
||||
(PInitializeConditionVariable) GetProcAddress(
|
||||
library, "InitializeConditionVariable");
|
||||
PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
|
||||
library, "SleepConditionVariableCS");
|
||||
PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
|
||||
library, "WakeConditionVariable");
|
||||
PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
|
||||
library, "WakeAllConditionVariable");
|
||||
|
||||
if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
|
||||
&& PWakeConditionVariable_ && PWakeAllConditionVariable_) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded native condition variables");
|
||||
win_support_condition_variables_primitive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!win_support_condition_variables_primitive) {
|
||||
return false;
|
||||
}
|
||||
PInitializeConditionVariable_(&condition_variable_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) {
|
||||
SleepCS(crit_sect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect,
|
||||
unsigned long max_time_in_ms) {
|
||||
CriticalSectionWindows* cs =
|
||||
static_cast<CriticalSectionWindows*>(&crit_sect);
|
||||
BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_,
|
||||
&(cs->crit), max_time_in_ms);
|
||||
return ret_val != 0;
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::Wake() {
|
||||
PWakeConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
void ConditionVariableNativeWin::WakeAll() {
|
||||
PWakeAllConditionVariable_(&condition_variable_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/condition_variable_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if !defined CONDITION_VARIABLE_INIT
|
||||
typedef struct RTL_CONDITION_VARIABLE_ {
|
||||
void* Ptr;
|
||||
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
||||
|
||||
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
||||
#endif
|
||||
|
||||
typedef void (WINAPI* PInitializeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef BOOL (WINAPI* PSleepConditionVariableCS)(PCONDITION_VARIABLE,
|
||||
PCRITICAL_SECTION, DWORD);
|
||||
typedef void (WINAPI* PWakeConditionVariable)(PCONDITION_VARIABLE);
|
||||
typedef void (WINAPI* PWakeAllConditionVariable)(PCONDITION_VARIABLE);
|
||||
|
||||
class ConditionVariableNativeWin : public ConditionVariableWrapper {
|
||||
public:
|
||||
static ConditionVariableWrapper* Create();
|
||||
virtual ~ConditionVariableNativeWin();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& crit_sect);
|
||||
bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
ConditionVariableNativeWin();
|
||||
|
||||
bool Init();
|
||||
|
||||
CONDITION_VARIABLE condition_variable_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_
|
@ -10,13 +10,15 @@
|
||||
|
||||
// Parts of this file derived from Chromium's base/cpu.cc.
|
||||
|
||||
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
#include "system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
namespace webrtc {
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
@ -25,23 +27,40 @@ int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
// xgetbv returns the value of an Intel Extended Control Register (XCR).
|
||||
// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
|
||||
static uint64_t xgetbv(uint32_t xcr) {
|
||||
#if defined(_MSC_VER)
|
||||
return _xgetbv(xcr);
|
||||
#else
|
||||
uint32_t eax, edx;
|
||||
|
||||
__asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
|
||||
return (static_cast<uint64_t>(edx) << 32) | eax;
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
|
||||
#ifndef _MSC_VER
|
||||
// Intrinsic for "cpuid".
|
||||
#if defined(__pic__) && defined(__i386__)
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile(
|
||||
"mov %%ebx, %%edi\n"
|
||||
"cpuid\n"
|
||||
"xchg %%edi, %%ebx\n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
"mov %%ebx, %%edi\n"
|
||||
"cpuid\n"
|
||||
"xchg %%edi, %%ebx\n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
#else
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile(
|
||||
"cpuid\n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
__asm__ volatile("cpuid\n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type), "c"(0));
|
||||
}
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
@ -49,7 +68,7 @@ static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
// Actual feature detection for x86.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
if (feature == kSSE2) {
|
||||
@ -58,15 +77,39 @@ static int GetCPUInfo(CPUFeature feature) {
|
||||
if (feature == kSSE3) {
|
||||
return 0 != (cpu_info[2] & 0x00000001);
|
||||
}
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
if (feature == kAVX2 &&
|
||||
!webrtc::field_trial::IsEnabled("WebRTC-Avx2SupportKillSwitch")) {
|
||||
int cpu_info7[4];
|
||||
__cpuid(cpu_info7, 0);
|
||||
int num_ids = cpu_info7[0];
|
||||
if (num_ids < 7) {
|
||||
return 0;
|
||||
}
|
||||
// Interpret CPU feature information.
|
||||
__cpuid(cpu_info7, 7);
|
||||
|
||||
// AVX instructions can be used when
|
||||
// a) AVX are supported by the CPU,
|
||||
// b) XSAVE is supported by the CPU,
|
||||
// c) XSAVE is enabled by the kernel.
|
||||
// See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
|
||||
// AVX2 support needs (avx_support && (cpu_info7[1] & 0x00000020) != 0;).
|
||||
return (cpu_info[2] & 0x10000000) != 0 &&
|
||||
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
|
||||
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
|
||||
(xgetbv(0) & 0x00000006) == 6 /* XSAVE enabled by kernel */ &&
|
||||
(cpu_info7[1] & 0x00000020) != 0;
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Default to straight C for other platforms.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfo = GetCPUInfo;
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM = GetCPUInfoNoASM;
|
||||
} // namespace webrtc
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/critical_section_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionWrapper* CriticalSectionWrapper::CreateCriticalSection() {
|
||||
#ifdef _WIN32
|
||||
return new CriticalSectionWindows();
|
||||
#else
|
||||
return new CriticalSectionPosix();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// General note: return values for the various pthread synchronization APIs
|
||||
// are explicitly ignored here. In Chromium, the same thing is done for release.
|
||||
// However, in debugging, failure in these APIs are logged.
|
||||
// TODO(henrike): add logging when pthread synchronization APIs are failing.
|
||||
|
||||
#include "webrtc/system_wrappers/source/critical_section_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionPosix::CriticalSectionPosix() {
|
||||
pthread_mutexattr_t attr;
|
||||
(void) pthread_mutexattr_init(&attr);
|
||||
(void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
(void) pthread_mutex_init(&mutex_, &attr);
|
||||
}
|
||||
|
||||
CriticalSectionPosix::~CriticalSectionPosix() {
|
||||
(void) pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionPosix::Enter() {
|
||||
(void) pthread_mutex_lock(&mutex_);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionPosix::Leave() {
|
||||
(void) pthread_mutex_unlock(&mutex_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionPosix : public CriticalSectionWrapper {
|
||||
public:
|
||||
CriticalSectionPosix();
|
||||
|
||||
~CriticalSectionPosix() override;
|
||||
|
||||
void Enter() override;
|
||||
void Leave() override;
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
friend class ConditionVariablePosix;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/critical_section_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CriticalSectionWindows::CriticalSectionWindows() {
|
||||
InitializeCriticalSection(&crit);
|
||||
}
|
||||
|
||||
CriticalSectionWindows::~CriticalSectionWindows() {
|
||||
DeleteCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Enter() {
|
||||
EnterCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Leave() {
|
||||
LeaveCriticalSection(&crit);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWindows : public CriticalSectionWrapper {
|
||||
public:
|
||||
CriticalSectionWindows();
|
||||
|
||||
virtual ~CriticalSectionWindows();
|
||||
|
||||
virtual void Enter();
|
||||
virtual void Leave();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION crit;
|
||||
|
||||
friend class ConditionVariableEventWin;
|
||||
friend class ConditionVariableNativeWin;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WIN_H_
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_win.h"
|
||||
#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_posix.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include "webrtc/system_wrappers/source/event_timer_posix.h"
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventWrapperImpl : public EventWrapper {
|
||||
public:
|
||||
EventWrapperImpl() : event_(false, false) {}
|
||||
~EventWrapperImpl() override {}
|
||||
|
||||
bool Set() override {
|
||||
event_.Set();
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper Wait(unsigned long max_time) override {
|
||||
int to_wait = max_time == WEBRTC_EVENT_INFINITE ?
|
||||
rtc::Event::kForever : static_cast<int>(max_time);
|
||||
return event_.Wait(to_wait) ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::Event event_;
|
||||
};
|
||||
|
||||
// static
|
||||
EventWrapper* EventWrapper::Create() {
|
||||
return new EventWrapperImpl();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/event_timer_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
EventTimerWrapper* EventTimerWrapper::Create() {
|
||||
return new EventTimerPosix();
|
||||
}
|
||||
|
||||
const long int E6 = 1000000;
|
||||
const long int E9 = 1000 * E6;
|
||||
|
||||
EventTimerPosix::EventTimerPosix()
|
||||
: event_set_(false),
|
||||
timer_thread_(nullptr),
|
||||
created_at_(),
|
||||
periodic_(false),
|
||||
time_(0),
|
||||
count_(0) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mutex_, &attr);
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
pthread_cond_init(&cond_, 0);
|
||||
#else
|
||||
pthread_condattr_t cond_attr;
|
||||
pthread_condattr_init(&cond_attr);
|
||||
pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
|
||||
pthread_cond_init(&cond_, &cond_attr);
|
||||
pthread_condattr_destroy(&cond_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
EventTimerPosix::~EventTimerPosix() {
|
||||
StopTimer();
|
||||
pthread_cond_destroy(&cond_);
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
// TODO(pbos): Make this void.
|
||||
bool EventTimerPosix::Set() {
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
event_set_ = true;
|
||||
pthread_cond_signal(&cond_);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerPosix::Wait(unsigned long timeout) {
|
||||
int ret_val = 0;
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
|
||||
if (!event_set_) {
|
||||
if (WEBRTC_EVENT_INFINITE != timeout) {
|
||||
timespec end_at;
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &end_at);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_at);
|
||||
#endif
|
||||
#else
|
||||
timeval value;
|
||||
struct timezone time_zone;
|
||||
time_zone.tz_minuteswest = 0;
|
||||
time_zone.tz_dsttime = 0;
|
||||
gettimeofday(&value, &time_zone);
|
||||
TIMEVAL_TO_TIMESPEC(&value, &end_at);
|
||||
#endif
|
||||
end_at.tv_sec += timeout / 1000;
|
||||
end_at.tv_nsec += (timeout - (timeout / 1000) * 1000) * E6;
|
||||
|
||||
if (end_at.tv_nsec >= E9) {
|
||||
end_at.tv_sec++;
|
||||
end_at.tv_nsec -= E9;
|
||||
}
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
|
||||
} else {
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_wait(&cond_, &mutex_);
|
||||
}
|
||||
}
|
||||
|
||||
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
|
||||
|
||||
// Reset and signal if set, regardless of why the thread woke up.
|
||||
if (event_set_) {
|
||||
ret_val = 0;
|
||||
event_set_ = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return ret_val == 0 ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerPosix::Wait(timespec* end_at) {
|
||||
int ret_val = 0;
|
||||
RTC_CHECK_EQ(0, pthread_mutex_lock(&mutex_));
|
||||
|
||||
while (ret_val == 0 && !event_set_)
|
||||
ret_val = pthread_cond_timedwait(&cond_, &mutex_, end_at);
|
||||
|
||||
RTC_DCHECK(ret_val == 0 || ret_val == ETIMEDOUT);
|
||||
|
||||
// Reset and signal if set, regardless of why the thread woke up.
|
||||
if (event_set_) {
|
||||
ret_val = 0;
|
||||
event_set_ = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return ret_val == 0 ? kEventSignaled : kEventTimeout;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::StartTimer(bool periodic, unsigned long time) {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (timer_thread_) {
|
||||
if (periodic_) {
|
||||
// Timer already started.
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return false;
|
||||
} else {
|
||||
// New one shot timer
|
||||
time_ = time;
|
||||
created_at_.tv_sec = 0;
|
||||
timer_event_->Set();
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the timer thread
|
||||
timer_event_.reset(new EventTimerPosix());
|
||||
const char* thread_name = "WebRtc_event_timer_thread";
|
||||
timer_thread_ = ThreadWrapper::CreateThread(Run, this, thread_name);
|
||||
periodic_ = periodic;
|
||||
time_ = time;
|
||||
bool started = timer_thread_->Start();
|
||||
timer_thread_->SetPriority(kRealtimePriority);
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::Run(void* obj) {
|
||||
return static_cast<EventTimerPosix*>(obj)->Process();
|
||||
}
|
||||
|
||||
bool EventTimerPosix::Process() {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (created_at_.tv_sec == 0) {
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &created_at_);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &created_at_);
|
||||
#endif
|
||||
#else
|
||||
timeval value;
|
||||
struct timezone time_zone;
|
||||
time_zone.tz_minuteswest = 0;
|
||||
time_zone.tz_dsttime = 0;
|
||||
gettimeofday(&value, &time_zone);
|
||||
TIMEVAL_TO_TIMESPEC(&value, &created_at_);
|
||||
#endif
|
||||
count_ = 0;
|
||||
}
|
||||
|
||||
timespec end_at;
|
||||
unsigned long long time = time_ * ++count_;
|
||||
end_at.tv_sec = created_at_.tv_sec + time / 1000;
|
||||
end_at.tv_nsec = created_at_.tv_nsec + (time - (time / 1000) * 1000) * E6;
|
||||
|
||||
if (end_at.tv_nsec >= E9) {
|
||||
end_at.tv_sec++;
|
||||
end_at.tv_nsec -= E9;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
if (timer_event_->Wait(&end_at) == kEventSignaled)
|
||||
return true;
|
||||
|
||||
pthread_mutex_lock(&mutex_);
|
||||
if (periodic_ || count_ == 1)
|
||||
Set();
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventTimerPosix::StopTimer() {
|
||||
if (timer_event_) {
|
||||
timer_event_->Set();
|
||||
}
|
||||
if (timer_thread_) {
|
||||
if (!timer_thread_->Stop()) {
|
||||
return false;
|
||||
}
|
||||
timer_thread_.reset();
|
||||
}
|
||||
timer_event_.reset();
|
||||
|
||||
// Set time to zero to force new reference time for the timer.
|
||||
memset(&created_at_, 0, sizeof(created_at_));
|
||||
count_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum State {
|
||||
kUp = 1,
|
||||
kDown = 2
|
||||
};
|
||||
|
||||
class EventTimerPosix : public EventTimerWrapper {
|
||||
public:
|
||||
EventTimerPosix();
|
||||
~EventTimerPosix() override;
|
||||
|
||||
EventTypeWrapper Wait(unsigned long max_time) override;
|
||||
bool Set() override;
|
||||
|
||||
bool StartTimer(bool periodic, unsigned long time) override;
|
||||
bool StopTimer() override;
|
||||
|
||||
private:
|
||||
static bool Run(void* obj);
|
||||
bool Process();
|
||||
EventTypeWrapper Wait(timespec* end_at);
|
||||
|
||||
private:
|
||||
pthread_cond_t cond_;
|
||||
pthread_mutex_t mutex_;
|
||||
bool event_set_;
|
||||
|
||||
rtc::scoped_ptr<ThreadWrapper> timer_thread_;
|
||||
rtc::scoped_ptr<EventTimerPosix> timer_event_;
|
||||
timespec created_at_;
|
||||
|
||||
bool periodic_;
|
||||
unsigned long time_; // In ms
|
||||
unsigned long count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_POSIX_H_
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/event_timer_win.h"
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// static
|
||||
EventTimerWrapper* EventTimerWrapper::Create() {
|
||||
return new EventTimerWin();
|
||||
}
|
||||
|
||||
EventTimerWin::EventTimerWin()
|
||||
: event_(::CreateEvent(NULL, // security attributes
|
||||
FALSE, // manual reset
|
||||
FALSE, // initial state
|
||||
NULL)), // name of event
|
||||
timerID_(NULL) {
|
||||
}
|
||||
|
||||
EventTimerWin::~EventTimerWin() {
|
||||
StopTimer();
|
||||
CloseHandle(event_);
|
||||
}
|
||||
|
||||
bool EventTimerWin::Set() {
|
||||
// Note: setting an event that is already set has no effect.
|
||||
return SetEvent(event_) == 1;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventTimerWin::Wait(unsigned long max_time) {
|
||||
unsigned long res = WaitForSingleObject(event_, max_time);
|
||||
switch (res) {
|
||||
case WAIT_OBJECT_0:
|
||||
return kEventSignaled;
|
||||
case WAIT_TIMEOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventTimerWin::StartTimer(bool periodic, unsigned long time) {
|
||||
if (timerID_ != NULL) {
|
||||
timeKillEvent(timerID_);
|
||||
timerID_ = NULL;
|
||||
}
|
||||
|
||||
if (periodic) {
|
||||
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
|
||||
TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE);
|
||||
} else {
|
||||
timerID_ = timeSetEvent(time, 0, (LPTIMECALLBACK)HANDLE(event_), 0,
|
||||
TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
|
||||
}
|
||||
|
||||
return timerID_ != NULL;
|
||||
}
|
||||
|
||||
bool EventTimerWin::StopTimer() {
|
||||
if (timerID_ != NULL) {
|
||||
timeKillEvent(timerID_);
|
||||
timerID_ = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventTimerWin : public EventTimerWrapper {
|
||||
public:
|
||||
EventTimerWin();
|
||||
virtual ~EventTimerWin();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long max_time);
|
||||
virtual bool Set();
|
||||
|
||||
virtual bool StartTimer(bool periodic, unsigned long time);
|
||||
virtual bool StopTimer();
|
||||
|
||||
private:
|
||||
HANDLE event_;
|
||||
uint32_t timerID_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
|
155
webrtc/system_wrappers/source/field_trial.cc
Normal file
155
webrtc/system_wrappers/source/field_trial.cc
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
|
||||
// Simple field trial implementation, which allows client to
|
||||
// specify desired flags in InitFieldTrialsFromString.
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
static const char* trials_init_string = NULL;
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
namespace {
|
||||
constexpr char kPersistentStringSeparator = '/';
|
||||
// Validates the given field trial string.
|
||||
// E.g.:
|
||||
// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
|
||||
// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial
|
||||
// and to group "Enabled100kbps" on WebRTCExperimentBar.
|
||||
//
|
||||
// E.g. invalid config:
|
||||
// "WebRTC-experiment1/Enabled" (note missing / separator at the end).
|
||||
bool FieldTrialsStringIsValidInternal(const absl::string_view trials) {
|
||||
if (trials.empty())
|
||||
return true;
|
||||
|
||||
size_t next_item = 0;
|
||||
std::map<absl::string_view, absl::string_view> field_trials;
|
||||
while (next_item < trials.length()) {
|
||||
size_t name_end = trials.find(kPersistentStringSeparator, next_item);
|
||||
if (name_end == trials.npos || next_item == name_end)
|
||||
return false;
|
||||
size_t group_name_end =
|
||||
trials.find(kPersistentStringSeparator, name_end + 1);
|
||||
if (group_name_end == trials.npos || name_end + 1 == group_name_end)
|
||||
return false;
|
||||
absl::string_view name = trials.substr(next_item, name_end - next_item);
|
||||
absl::string_view group_name =
|
||||
trials.substr(name_end + 1, group_name_end - name_end - 1);
|
||||
|
||||
next_item = group_name_end + 1;
|
||||
|
||||
// Fail if duplicate with different group name.
|
||||
if (field_trials.find(name) != field_trials.end() &&
|
||||
field_trials.find(name)->second != group_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
field_trials[name] = group_name;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool FieldTrialsStringIsValid(const char* trials_string) {
|
||||
return FieldTrialsStringIsValidInternal(trials_string);
|
||||
}
|
||||
|
||||
void InsertOrReplaceFieldTrialStringsInMap(
|
||||
std::map<std::string, std::string>* fieldtrial_map,
|
||||
const absl::string_view trials_string) {
|
||||
if (FieldTrialsStringIsValidInternal(trials_string)) {
|
||||
std::vector<std::string> tokens;
|
||||
rtc::split(std::string(trials_string), '/', &tokens);
|
||||
// Skip last token which is empty due to trailing '/'.
|
||||
for (size_t idx = 0; idx < tokens.size() - 1; idx += 2) {
|
||||
(*fieldtrial_map)[tokens[idx]] = tokens[idx + 1];
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK(false) << "Invalid field trials string:" << trials_string;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MergeFieldTrialsStrings(const char* first, const char* second) {
|
||||
std::map<std::string, std::string> fieldtrial_map;
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, first);
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, second);
|
||||
|
||||
// Merge into fieldtrial string.
|
||||
std::string merged = "";
|
||||
for (auto const& fieldtrial : fieldtrial_map) {
|
||||
merged += fieldtrial.first + '/' + fieldtrial.second + '/';
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
std::string FindFullName(const std::string& name) {
|
||||
if (trials_init_string == NULL)
|
||||
return std::string();
|
||||
|
||||
std::string trials_string(trials_init_string);
|
||||
if (trials_string.empty())
|
||||
return std::string();
|
||||
|
||||
size_t next_item = 0;
|
||||
while (next_item < trials_string.length()) {
|
||||
// Find next name/value pair in field trial configuration string.
|
||||
size_t field_name_end =
|
||||
trials_string.find(kPersistentStringSeparator, next_item);
|
||||
if (field_name_end == trials_string.npos || field_name_end == next_item)
|
||||
break;
|
||||
size_t field_value_end =
|
||||
trials_string.find(kPersistentStringSeparator, field_name_end + 1);
|
||||
if (field_value_end == trials_string.npos ||
|
||||
field_value_end == field_name_end + 1)
|
||||
break;
|
||||
std::string field_name(trials_string, next_item,
|
||||
field_name_end - next_item);
|
||||
std::string field_value(trials_string, field_name_end + 1,
|
||||
field_value_end - field_name_end - 1);
|
||||
next_item = field_value_end + 1;
|
||||
|
||||
if (name == field_name)
|
||||
return field_value;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
|
||||
// Optionally initialize field trial from a string.
|
||||
void InitFieldTrialsFromString(const char* trials_string) {
|
||||
RTC_LOG(LS_INFO) << "Setting field trial string:" << trials_string;
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
if (trials_string) {
|
||||
RTC_DCHECK(FieldTrialsStringIsValidInternal(trials_string))
|
||||
<< "Invalid field trials string:" << trials_string;
|
||||
};
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
trials_init_string = trials_string;
|
||||
}
|
||||
|
||||
const char* GetFieldTrialString() {
|
||||
return trials_init_string;
|
||||
}
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/file_impl.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FileWrapper* FileWrapper::Create() {
|
||||
return new FileWrapperImpl();
|
||||
}
|
||||
|
||||
FileWrapperImpl::FileWrapperImpl()
|
||||
: rw_lock_(RWLockWrapper::CreateRWLock()),
|
||||
id_(NULL),
|
||||
managed_file_handle_(true),
|
||||
open_(false),
|
||||
looping_(false),
|
||||
read_only_(false),
|
||||
max_size_in_bytes_(0),
|
||||
size_in_bytes_(0) {
|
||||
memset(file_name_utf8_, 0, kMaxFileNameSize);
|
||||
}
|
||||
|
||||
FileWrapperImpl::~FileWrapperImpl() {
|
||||
if (id_ != NULL && managed_file_handle_) {
|
||||
fclose(id_);
|
||||
}
|
||||
}
|
||||
|
||||
int FileWrapperImpl::CloseFile() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
return CloseFileImpl();
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Rewind() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (looping_ || !read_only_) {
|
||||
if (id_ != NULL) {
|
||||
size_in_bytes_ = 0;
|
||||
return fseek(id_, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::SetMaxFileSize(size_t bytes) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
max_size_in_bytes_ = bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Flush() {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
return FlushImpl();
|
||||
}
|
||||
|
||||
int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const {
|
||||
ReadLockScoped read(*rw_lock_);
|
||||
size_t length = strlen(file_name_utf8_);
|
||||
if (length > kMaxFileNameSize) {
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
if (length < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make sure to NULL terminate
|
||||
if (size < length) {
|
||||
length = size - 1;
|
||||
}
|
||||
memcpy(file_name_utf8, file_name_utf8_, length);
|
||||
file_name_utf8[length] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FileWrapperImpl::Open() const {
|
||||
ReadLockScoped read(*rw_lock_);
|
||||
return open_;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only,
|
||||
bool loop, bool text) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (id_ != NULL && !managed_file_handle_)
|
||||
return -1;
|
||||
size_t length = strlen(file_name_utf8);
|
||||
if (length > kMaxFileNameSize - 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_only_ = read_only;
|
||||
|
||||
FILE* tmp_id = NULL;
|
||||
#if defined _WIN32
|
||||
wchar_t wide_file_name[kMaxFileNameSize];
|
||||
wide_file_name[0] = 0;
|
||||
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0, // UTF8 flag
|
||||
file_name_utf8,
|
||||
-1, // Null terminated string
|
||||
wide_file_name,
|
||||
kMaxFileNameSize);
|
||||
if (text) {
|
||||
if (read_only) {
|
||||
tmp_id = _wfopen(wide_file_name, L"rt");
|
||||
} else {
|
||||
tmp_id = _wfopen(wide_file_name, L"wt");
|
||||
}
|
||||
} else {
|
||||
if (read_only) {
|
||||
tmp_id = _wfopen(wide_file_name, L"rb");
|
||||
} else {
|
||||
tmp_id = _wfopen(wide_file_name, L"wb");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (text) {
|
||||
if (read_only) {
|
||||
tmp_id = fopen(file_name_utf8, "rt");
|
||||
} else {
|
||||
tmp_id = fopen(file_name_utf8, "wt");
|
||||
}
|
||||
} else {
|
||||
if (read_only) {
|
||||
tmp_id = fopen(file_name_utf8, "rb");
|
||||
} else {
|
||||
tmp_id = fopen(file_name_utf8, "wb");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmp_id != NULL) {
|
||||
// +1 comes from copying the NULL termination character.
|
||||
memcpy(file_name_utf8_, file_name_utf8, length + 1);
|
||||
if (id_ != NULL) {
|
||||
fclose(id_);
|
||||
}
|
||||
id_ = tmp_id;
|
||||
managed_file_handle_ = true;
|
||||
looping_ = loop;
|
||||
open_ = true;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
if (id_ != NULL) {
|
||||
if (managed_file_handle_)
|
||||
fclose(id_);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
id_ = handle;
|
||||
managed_file_handle_ = manage_file;
|
||||
read_only_ = read_only;
|
||||
looping_ = loop;
|
||||
open_ = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Read(void* buf, size_t length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (id_ == NULL)
|
||||
return -1;
|
||||
|
||||
size_t bytes_read = fread(buf, 1, length, id_);
|
||||
if (bytes_read != length && !looping_) {
|
||||
CloseFileImpl();
|
||||
}
|
||||
return static_cast<int>(bytes_read);
|
||||
}
|
||||
|
||||
int FileWrapperImpl::WriteText(const char* format, ...) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (format == NULL)
|
||||
return -1;
|
||||
|
||||
if (read_only_)
|
||||
return -1;
|
||||
|
||||
if (id_ == NULL)
|
||||
return -1;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int num_chars = vfprintf(id_, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (num_chars >= 0) {
|
||||
return num_chars;
|
||||
} else {
|
||||
CloseFileImpl();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileWrapperImpl::Write(const void* buf, size_t length) {
|
||||
WriteLockScoped write(*rw_lock_);
|
||||
if (buf == NULL)
|
||||
return false;
|
||||
|
||||
if (read_only_)
|
||||
return false;
|
||||
|
||||
if (id_ == NULL)
|
||||
return false;
|
||||
|
||||
// Check if it's time to stop writing.
|
||||
if (max_size_in_bytes_ > 0 &&
|
||||
(size_in_bytes_ + length) > max_size_in_bytes_) {
|
||||
FlushImpl();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_bytes = fwrite(buf, 1, length, id_);
|
||||
if (num_bytes > 0) {
|
||||
size_in_bytes_ += num_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
CloseFileImpl();
|
||||
return false;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::CloseFileImpl() {
|
||||
if (id_ != NULL) {
|
||||
if (managed_file_handle_)
|
||||
fclose(id_);
|
||||
id_ = NULL;
|
||||
}
|
||||
memset(file_name_utf8_, 0, kMaxFileNameSize);
|
||||
open_ = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::FlushImpl() {
|
||||
if (id_ != NULL) {
|
||||
return fflush(id_);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapper::Rewind() {
|
||||
RTC_DCHECK(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWrapper;
|
||||
|
||||
class FileWrapperImpl : public FileWrapper {
|
||||
public:
|
||||
FileWrapperImpl();
|
||||
~FileWrapperImpl() override;
|
||||
|
||||
int FileName(char* file_name_utf8, size_t size) const override;
|
||||
|
||||
bool Open() const override;
|
||||
|
||||
int OpenFile(const char* file_name_utf8,
|
||||
bool read_only,
|
||||
bool loop = false,
|
||||
bool text = false) override;
|
||||
|
||||
int OpenFromFileHandle(FILE* handle,
|
||||
bool manage_file,
|
||||
bool read_only,
|
||||
bool loop = false) override;
|
||||
|
||||
int CloseFile() override;
|
||||
int SetMaxFileSize(size_t bytes) override;
|
||||
int Flush() override;
|
||||
|
||||
int Read(void* buf, size_t length) override;
|
||||
bool Write(const void* buf, size_t length) override;
|
||||
int WriteText(const char* format, ...) override;
|
||||
int Rewind() override;
|
||||
|
||||
private:
|
||||
int CloseFileImpl();
|
||||
int FlushImpl();
|
||||
|
||||
rtc::scoped_ptr<RWLockWrapper> rw_lock_;
|
||||
|
||||
FILE* id_;
|
||||
bool managed_file_handle_;
|
||||
bool open_;
|
||||
bool looping_;
|
||||
bool read_only_;
|
||||
size_t max_size_in_bytes_; // -1 indicates file size limitation is off
|
||||
size_t size_in_bytes_;
|
||||
char file_name_utf8_[kMaxFileNameSize];
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/logging.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
TraceLevel WebRtcSeverity(LoggingSeverity sev) {
|
||||
switch (sev) {
|
||||
// TODO(ajm): SENSITIVE doesn't have a corresponding webrtc level.
|
||||
case LS_SENSITIVE: return kTraceInfo;
|
||||
case LS_VERBOSE: return kTraceInfo;
|
||||
case LS_INFO: return kTraceTerseInfo;
|
||||
case LS_WARNING: return kTraceWarning;
|
||||
case LS_ERROR: return kTraceError;
|
||||
default: return kTraceNone;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the filename portion of the string (that following the last slash).
|
||||
const char* FilenameFromPath(const char* file) {
|
||||
const char* end1 = ::strrchr(file, '/');
|
||||
const char* end2 = ::strrchr(file, '\\');
|
||||
if (!end1 && !end2)
|
||||
return file;
|
||||
else
|
||||
return (end1 > end2) ? end1 + 1 : end2 + 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev)
|
||||
: severity_(sev) {
|
||||
print_stream_ << "(" << FilenameFromPath(file) << ":" << line << "): ";
|
||||
}
|
||||
|
||||
bool LogMessage::Loggable(LoggingSeverity sev) {
|
||||
// |level_filter| is a bitmask, unlike libjingle's minimum severity value.
|
||||
return WebRtcSeverity(sev) & Trace::level_filter() ? true : false;
|
||||
}
|
||||
|
||||
LogMessage::~LogMessage() {
|
||||
const std::string& str = print_stream_.str();
|
||||
Trace::Add(WebRtcSeverity(severity_), kTraceUndefined, 0, "%s", str.c_str());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
328
webrtc/system_wrappers/source/metrics.cc
Normal file
328
webrtc/system_wrappers/source/metrics.cc
Normal file
@ -0,0 +1,328 @@
|
||||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
// Default implementation of histogram methods for WebRTC clients that do not
|
||||
// want to provide their own implementation.
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
class Histogram;
|
||||
|
||||
namespace {
|
||||
// Limit for the maximum number of sample values that can be stored.
|
||||
// TODO(asapersson): Consider using bucket count (and set up
|
||||
// linearly/exponentially spaced buckets) if samples are logged more frequently.
|
||||
const int kMaxSampleMapSize = 300;
|
||||
|
||||
class RtcHistogram {
|
||||
public:
|
||||
RtcHistogram(const std::string& name, int min, int max, int bucket_count)
|
||||
: min_(min), max_(max), info_(name, min, max, bucket_count) {
|
||||
RTC_DCHECK_GT(bucket_count, 0);
|
||||
}
|
||||
|
||||
void Add(int sample) {
|
||||
sample = std::min(sample, max_);
|
||||
sample = std::max(sample, min_ - 1); // Underflow bucket.
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.size() == kMaxSampleMapSize &&
|
||||
info_.samples.find(sample) == info_.samples.end()) {
|
||||
return;
|
||||
}
|
||||
++info_.samples[sample];
|
||||
}
|
||||
|
||||
// Returns a copy (or nullptr if there are no samples) and clears samples.
|
||||
std::unique_ptr<SampleInfo> GetAndReset() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.empty())
|
||||
return nullptr;
|
||||
|
||||
SampleInfo* copy =
|
||||
new SampleInfo(info_.name, info_.min, info_.max, info_.bucket_count);
|
||||
|
||||
std::swap(info_.samples, copy->samples);
|
||||
|
||||
return std::unique_ptr<SampleInfo>(copy);
|
||||
}
|
||||
|
||||
const std::string& name() const { return info_.name; }
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
info_.samples.clear();
|
||||
}
|
||||
|
||||
int NumEvents(int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto it = info_.samples.find(sample);
|
||||
return (it == info_.samples.end()) ? 0 : it->second;
|
||||
}
|
||||
|
||||
int NumSamples() const {
|
||||
int num_samples = 0;
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& sample : info_.samples) {
|
||||
num_samples += sample.second;
|
||||
}
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
int MinSample() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return (info_.samples.empty()) ? -1 : info_.samples.begin()->first;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return info_.samples;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
const int min_;
|
||||
const int max_;
|
||||
SampleInfo info_ RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogram);
|
||||
};
|
||||
|
||||
class RtcHistogramMap {
|
||||
public:
|
||||
RtcHistogramMap() {}
|
||||
~RtcHistogramMap() {}
|
||||
|
||||
Histogram* GetCountsHistogram(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, min, max, bucket_count);
|
||||
map_[name].reset(hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
Histogram* GetEnumerationHistogram(const std::string& name, int boundary) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, 1, boundary, boundary + 1);
|
||||
map_[name].reset(hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_) {
|
||||
std::unique_ptr<SampleInfo> info = kv.second->GetAndReset();
|
||||
if (info)
|
||||
histograms->insert(std::make_pair(kv.first, std::move(info)));
|
||||
}
|
||||
}
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_)
|
||||
kv.second->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumEvents(sample);
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumSamples();
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? -1 : it->second->MinSample();
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? std::map<int, int>() : it->second->Samples();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
std::map<std::string, std::unique_ptr<RtcHistogram>> map_
|
||||
RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogramMap);
|
||||
};
|
||||
|
||||
// RtcHistogramMap is allocated upon call to Enable().
|
||||
// The histogram getter functions, which return pointer values to the histograms
|
||||
// in the map, are cached in WebRTC. Therefore, this memory is not freed by the
|
||||
// application (the memory will be reclaimed by the OS).
|
||||
static RtcHistogramMap* volatile g_rtc_histogram_map = nullptr;
|
||||
|
||||
void CreateMap() {
|
||||
RtcHistogramMap* map = rtc::AtomicOps::AcquireLoadPtr(&g_rtc_histogram_map);
|
||||
if (map == nullptr) {
|
||||
RtcHistogramMap* new_map = new RtcHistogramMap();
|
||||
RtcHistogramMap* old_map = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
&g_rtc_histogram_map, static_cast<RtcHistogramMap*>(nullptr), new_map);
|
||||
if (old_map != nullptr)
|
||||
delete new_map;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first time we start using histograms. Used to make sure Enable() is
|
||||
// not called thereafter.
|
||||
#if RTC_DCHECK_IS_ON
|
||||
static volatile int g_rtc_histogram_called = 0;
|
||||
#endif
|
||||
|
||||
// Gets the map (or nullptr).
|
||||
RtcHistogramMap* GetMap() {
|
||||
#if RTC_DCHECK_IS_ON
|
||||
rtc::AtomicOps::ReleaseStore(&g_rtc_histogram_called, 1);
|
||||
#endif
|
||||
return g_rtc_histogram_map;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
// Implementation of histogram methods in
|
||||
// webrtc/system_wrappers/interface/metrics.h.
|
||||
|
||||
// Histogram with exponentially spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
// TODO(asapersson): Alternative implementation will be needed if this
|
||||
// histogram type should be truly exponential.
|
||||
return HistogramFactoryGetCountsLinear(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetCountsHistogram(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetEnumerationHistogram(name, boundary);
|
||||
}
|
||||
|
||||
// Our default implementation reuses the non-sparse histogram.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) {
|
||||
return HistogramFactoryGetEnumeration(name, boundary);
|
||||
}
|
||||
|
||||
// Fast path. Adds |sample| to cached |histogram_pointer|.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample) {
|
||||
RtcHistogram* ptr = reinterpret_cast<RtcHistogram*>(histogram_pointer);
|
||||
ptr->Add(sample);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
|
||||
SampleInfo::SampleInfo(const std::string& name,
|
||||
int min,
|
||||
int max,
|
||||
size_t bucket_count)
|
||||
: name(name), min(min), max(max), bucket_count(bucket_count) {}
|
||||
|
||||
SampleInfo::~SampleInfo() {}
|
||||
|
||||
// Implementation of global functions in metrics.h.
|
||||
void Enable() {
|
||||
RTC_DCHECK(g_rtc_histogram_map == nullptr);
|
||||
#if RTC_DCHECK_IS_ON
|
||||
RTC_DCHECK_EQ(0, rtc::AtomicOps::AcquireLoad(&g_rtc_histogram_called));
|
||||
#endif
|
||||
CreateMap();
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
histograms->clear();
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->GetAndReset(histograms);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumEvents(name, sample) : 0;
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumSamples(name) : 0;
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->MinSample(name) : -1;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->Samples(name) : std::map<int, int>();
|
||||
}
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
// Default implementation of histogram methods for WebRTC clients that do not
|
||||
// want to provide their own implementation.
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name, int min, int max,
|
||||
int bucket_count) { return NULL; }
|
||||
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary) { return NULL; }
|
||||
|
||||
void HistogramAdd(
|
||||
Histogram* histogram_pointer, const std::string& name, int sample) {}
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
|
||||
#include "webrtc/system_wrappers/source/rw_lock_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockWrapper* RWLockWrapper::CreateRWLock() {
|
||||
#ifdef _WIN32
|
||||
// Native implementation is faster, so use that if available.
|
||||
RWLockWrapper* lock = RWLockWin::Create();
|
||||
if (lock) {
|
||||
return lock;
|
||||
}
|
||||
return new RWLockGeneric();
|
||||
#else
|
||||
return RWLockPosix::Create();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_generic.h"
|
||||
|
||||
#include "webrtc/system_wrappers/include/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockGeneric::RWLockGeneric()
|
||||
: readers_active_(0),
|
||||
writer_active_(false),
|
||||
readers_waiting_(0),
|
||||
writers_waiting_(0) {
|
||||
critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
}
|
||||
|
||||
RWLockGeneric::~RWLockGeneric() {
|
||||
delete write_condition_;
|
||||
delete read_condition_;
|
||||
delete critical_section_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || readers_active_ > 0) {
|
||||
++writers_waiting_;
|
||||
while (writer_active_ || readers_active_ > 0) {
|
||||
write_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--writers_waiting_;
|
||||
}
|
||||
writer_active_ = true;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockExclusive() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
writer_active_ = false;
|
||||
if (writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
} else if (readers_waiting_ > 0) {
|
||||
read_condition_->WakeAll();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockGeneric::AcquireLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
if (writer_active_ || writers_waiting_ > 0) {
|
||||
++readers_waiting_;
|
||||
|
||||
while (writer_active_ || writers_waiting_ > 0) {
|
||||
read_condition_->SleepCS(*critical_section_);
|
||||
}
|
||||
--readers_waiting_;
|
||||
}
|
||||
++readers_active_;
|
||||
}
|
||||
|
||||
void RWLockGeneric::ReleaseLockShared() {
|
||||
CriticalSectionScoped cs(critical_section_);
|
||||
--readers_active_;
|
||||
if (readers_active_ == 0 && writers_waiting_ > 0) {
|
||||
write_condition_->Wake();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
class RWLockGeneric : public RWLockWrapper {
|
||||
public:
|
||||
RWLockGeneric();
|
||||
~RWLockGeneric() override;
|
||||
|
||||
void AcquireLockExclusive() override;
|
||||
void ReleaseLockExclusive() override;
|
||||
|
||||
void AcquireLockShared() override;
|
||||
void ReleaseLockShared() override;
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* critical_section_;
|
||||
ConditionVariableWrapper* read_condition_;
|
||||
ConditionVariableWrapper* write_condition_;
|
||||
|
||||
int readers_active_;
|
||||
bool writer_active_;
|
||||
int readers_waiting_;
|
||||
int writers_waiting_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RWLockPosix::RWLockPosix() : lock_() {
|
||||
}
|
||||
|
||||
RWLockPosix::~RWLockPosix() {
|
||||
pthread_rwlock_destroy(&lock_);
|
||||
}
|
||||
|
||||
RWLockPosix* RWLockPosix::Create() {
|
||||
RWLockPosix* ret_val = new RWLockPosix();
|
||||
if (!ret_val->Init()) {
|
||||
delete ret_val;
|
||||
return NULL;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
bool RWLockPosix::Init() {
|
||||
return pthread_rwlock_init(&lock_, 0) == 0;
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockExclusive() {
|
||||
pthread_rwlock_wrlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockExclusive() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::AcquireLockShared() {
|
||||
pthread_rwlock_rdlock(&lock_);
|
||||
}
|
||||
|
||||
void RWLockPosix::ReleaseLockShared() {
|
||||
pthread_rwlock_unlock(&lock_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockPosix : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockPosix* Create();
|
||||
~RWLockPosix() override;
|
||||
|
||||
void AcquireLockExclusive() override;
|
||||
void ReleaseLockExclusive() override;
|
||||
|
||||
void AcquireLockShared() override;
|
||||
void ReleaseLockShared() override;
|
||||
|
||||
private:
|
||||
RWLockPosix();
|
||||
bool Init();
|
||||
|
||||
pthread_rwlock_t lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/rw_lock_win.h"
|
||||
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static bool native_rw_locks_supported = false;
|
||||
static bool module_load_attempted = false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
typedef void (WINAPI* InitializeSRWLock)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockExclusive)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockExclusive)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI* AcquireSRWLockShared)(PSRWLOCK);
|
||||
typedef void (WINAPI* ReleaseSRWLockShared)(PSRWLOCK);
|
||||
|
||||
InitializeSRWLock initialize_srw_lock;
|
||||
AcquireSRWLockExclusive acquire_srw_lock_exclusive;
|
||||
AcquireSRWLockShared acquire_srw_lock_shared;
|
||||
ReleaseSRWLockShared release_srw_lock_shared;
|
||||
ReleaseSRWLockExclusive release_srw_lock_exclusive;
|
||||
|
||||
RWLockWin::RWLockWin() {
|
||||
initialize_srw_lock(&lock_);
|
||||
}
|
||||
|
||||
RWLockWin* RWLockWin::Create() {
|
||||
if (!LoadModule()) {
|
||||
return NULL;
|
||||
}
|
||||
return new RWLockWin();
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockExclusive() {
|
||||
acquire_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockExclusive() {
|
||||
release_srw_lock_exclusive(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::AcquireLockShared() {
|
||||
acquire_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
void RWLockWin::ReleaseLockShared() {
|
||||
release_srw_lock_shared(&lock_);
|
||||
}
|
||||
|
||||
bool RWLockWin::LoadModule() {
|
||||
if (module_load_attempted) {
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
module_load_attempted = true;
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if (!library) {
|
||||
return false;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
|
||||
|
||||
initialize_srw_lock =
|
||||
(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");
|
||||
|
||||
acquire_srw_lock_exclusive =
|
||||
(AcquireSRWLockExclusive)GetProcAddress(library,
|
||||
"AcquireSRWLockExclusive");
|
||||
release_srw_lock_exclusive =
|
||||
(ReleaseSRWLockExclusive)GetProcAddress(library,
|
||||
"ReleaseSRWLockExclusive");
|
||||
acquire_srw_lock_shared =
|
||||
(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
|
||||
release_srw_lock_shared =
|
||||
(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");
|
||||
|
||||
if (initialize_srw_lock && acquire_srw_lock_exclusive &&
|
||||
release_srw_lock_exclusive && acquire_srw_lock_shared &&
|
||||
release_srw_lock_shared) {
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Native RW Lock");
|
||||
native_rw_locks_supported = true;
|
||||
}
|
||||
return native_rw_locks_supported;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RWLockWin : public RWLockWrapper {
|
||||
public:
|
||||
static RWLockWin* Create();
|
||||
~RWLockWin() {}
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
private:
|
||||
RWLockWin();
|
||||
static bool LoadModule();
|
||||
|
||||
SRWLOCK lock_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN_H_
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "system_wrappers/include/sleep.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
// For Sleep()
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "webrtc/system_wrappers/source/thread_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/thread_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if defined(_WIN32)
|
||||
typedef ThreadWindows ThreadType;
|
||||
#else
|
||||
typedef ThreadPosix ThreadType;
|
||||
#endif
|
||||
|
||||
rtc::scoped_ptr<ThreadWrapper> ThreadWrapper::CreateThread(
|
||||
ThreadRunFunction func, void* obj, const char* thread_name) {
|
||||
return rtc::scoped_ptr<ThreadWrapper>(
|
||||
new ThreadType(func, obj, thread_name)).Pass();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/thread_posix.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef WEBRTC_LINUX
|
||||
#include <linux/unistd.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/sleep.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
struct ThreadAttributes {
|
||||
ThreadAttributes() { pthread_attr_init(&attr); }
|
||||
~ThreadAttributes() { pthread_attr_destroy(&attr); }
|
||||
pthread_attr_t* operator&() { return &attr; }
|
||||
pthread_attr_t attr;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
|
||||
int max_prio) {
|
||||
RTC_DCHECK(max_prio - min_prio > 2);
|
||||
const int top_prio = max_prio - 1;
|
||||
const int low_prio = min_prio + 1;
|
||||
|
||||
switch (priority) {
|
||||
case kLowPriority:
|
||||
return low_prio;
|
||||
case kNormalPriority:
|
||||
// The -1 ensures that the kHighPriority is always greater or equal to
|
||||
// kNormalPriority.
|
||||
return (low_prio + top_prio - 1) / 2;
|
||||
case kHighPriority:
|
||||
return std::max(top_prio - 2, low_prio);
|
||||
case kHighestPriority:
|
||||
return std::max(top_prio - 1, low_prio);
|
||||
case kRealtimePriority:
|
||||
return top_prio;
|
||||
}
|
||||
RTC_DCHECK(false);
|
||||
return low_prio;
|
||||
}
|
||||
|
||||
// static
|
||||
void* ThreadPosix::StartThread(void* param) {
|
||||
static_cast<ThreadPosix*>(param)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadPosix::ThreadPosix(ThreadRunFunction func, void* obj,
|
||||
const char* thread_name)
|
||||
: run_function_(func),
|
||||
obj_(obj),
|
||||
stop_event_(false, false),
|
||||
name_(thread_name ? thread_name : "webrtc"),
|
||||
thread_(0) {
|
||||
RTC_DCHECK(name_.length() < 64);
|
||||
}
|
||||
|
||||
uint32_t ThreadWrapper::GetThreadId() {
|
||||
return rtc::CurrentThreadId();
|
||||
}
|
||||
|
||||
ThreadPosix::~ThreadPosix() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
// TODO(pbos): Make Start void, calling code really doesn't support failures
|
||||
// here.
|
||||
bool ThreadPosix::Start() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_) << "Thread already started?";
|
||||
|
||||
ThreadAttributes attr;
|
||||
// Set the stack stack size to 1M.
|
||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||
RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadPosix::Stop() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!thread_)
|
||||
return true;
|
||||
|
||||
stop_event_.Set();
|
||||
RTC_CHECK_EQ(0, pthread_join(thread_, nullptr));
|
||||
thread_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadPosix::SetPriority(ThreadPriority priority) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!thread_)
|
||||
return false;
|
||||
#if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
|
||||
// TODO(tommi): Switch to the same mechanism as Chromium uses for
|
||||
// changing thread priorities.
|
||||
return true;
|
||||
#else
|
||||
#ifdef WEBRTC_THREAD_RR
|
||||
const int policy = SCHED_RR;
|
||||
#else
|
||||
const int policy = SCHED_FIFO;
|
||||
#endif
|
||||
const int min_prio = sched_get_priority_min(policy);
|
||||
const int max_prio = sched_get_priority_max(policy);
|
||||
if (min_prio == -1 || max_prio == -1) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
||||
"unable to retreive min or max priority for threads");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (max_prio - min_prio <= 2)
|
||||
return false;
|
||||
|
||||
sched_param param;
|
||||
param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio);
|
||||
if (pthread_setschedparam(thread_, policy, ¶m) != 0) {
|
||||
WEBRTC_TRACE(
|
||||
kTraceError, kTraceUtility, -1, "unable to set thread priority");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
|
||||
}
|
||||
|
||||
void ThreadPosix::Run() {
|
||||
if (!name_.empty()) {
|
||||
// Setting the thread name may fail (harmlessly) if running inside a
|
||||
// sandbox. Ignore failures if they happen.
|
||||
rtc::SetCurrentThreadName(name_.substr(0, 63).c_str());
|
||||
}
|
||||
|
||||
// It's a requirement that for successful thread creation that the run
|
||||
// function be called at least once (see RunFunctionIsCalled unit test),
|
||||
// so to fullfill that requirement, we use a |do| loop and not |while|.
|
||||
do {
|
||||
if (!run_function_(obj_))
|
||||
break;
|
||||
} while (!stop_event_.Wait(0));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_POSIX_H_
|
||||
|
||||
#include "webrtc/base/event.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
|
||||
int max_prio);
|
||||
|
||||
class ThreadPosix : public ThreadWrapper {
|
||||
public:
|
||||
ThreadPosix(ThreadRunFunction func, void* obj, const char* thread_name);
|
||||
~ThreadPosix() override;
|
||||
|
||||
// From ThreadWrapper.
|
||||
bool Start() override;
|
||||
bool Stop() override;
|
||||
|
||||
bool SetPriority(ThreadPriority priority) override;
|
||||
|
||||
private:
|
||||
static void* StartThread(void* param);
|
||||
|
||||
void Run();
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
ThreadRunFunction const run_function_;
|
||||
void* const obj_;
|
||||
rtc::Event stop_event_;
|
||||
const std::string name_;
|
||||
|
||||
pthread_t thread_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_POSIX_H_
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/thread_win.h"
|
||||
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
void CALLBACK RaiseFlag(ULONG_PTR param) {
|
||||
*reinterpret_cast<bool*>(param) = true;
|
||||
}
|
||||
}
|
||||
|
||||
ThreadWindows::ThreadWindows(ThreadRunFunction func, void* obj,
|
||||
const char* thread_name)
|
||||
: run_function_(func),
|
||||
obj_(obj),
|
||||
stop_(false),
|
||||
thread_(NULL),
|
||||
name_(thread_name ? thread_name : "webrtc") {
|
||||
RTC_DCHECK(func);
|
||||
}
|
||||
|
||||
ThreadWindows::~ThreadWindows() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_);
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t ThreadWrapper::GetThreadId() {
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
// static
|
||||
DWORD WINAPI ThreadWindows::StartThread(void* param) {
|
||||
static_cast<ThreadWindows*>(param)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Start() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
RTC_DCHECK(!thread_);
|
||||
|
||||
stop_ = false;
|
||||
|
||||
// See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
|
||||
// Set the reserved stack stack size to 1M, which is the default on Windows
|
||||
// and Linux.
|
||||
DWORD thread_id;
|
||||
thread_ = ::CreateThread(NULL, 1024 * 1024, &StartThread, this,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id);
|
||||
if (!thread_ ) {
|
||||
RTC_DCHECK(false) << "CreateThread failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Stop() {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
if (thread_) {
|
||||
// Set stop_ to |true| on the worker thread.
|
||||
QueueUserAPC(&RaiseFlag, thread_, reinterpret_cast<ULONG_PTR>(&stop_));
|
||||
WaitForSingleObject(thread_, INFINITE);
|
||||
CloseHandle(thread_);
|
||||
thread_ = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadWindows::SetPriority(ThreadPriority priority) {
|
||||
RTC_DCHECK(main_thread_.CalledOnValidThread());
|
||||
return thread_ && SetThreadPriority(thread_, priority);
|
||||
}
|
||||
|
||||
void ThreadWindows::Run() {
|
||||
if (!name_.empty())
|
||||
rtc::SetCurrentThreadName(name_.c_str());
|
||||
|
||||
do {
|
||||
// The interface contract of Start/Stop is that for a successfull call to
|
||||
// Start, there should be at least one call to the run function. So we
|
||||
// call the function before checking |stop_|.
|
||||
if (!run_function_(obj_))
|
||||
break;
|
||||
// Alertable sleep to permit RaiseFlag to run and update |stop_|.
|
||||
SleepEx(0, true);
|
||||
} while (!stop_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WIN_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ThreadWindows : public ThreadWrapper {
|
||||
public:
|
||||
ThreadWindows(ThreadRunFunction func, void* obj, const char* thread_name);
|
||||
~ThreadWindows() override;
|
||||
|
||||
bool Start() override;
|
||||
bool Stop() override;
|
||||
|
||||
bool SetPriority(ThreadPriority priority) override;
|
||||
|
||||
protected:
|
||||
void Run();
|
||||
|
||||
private:
|
||||
static DWORD WINAPI StartThread(void* param);
|
||||
|
||||
ThreadRunFunction const run_function_;
|
||||
void* const obj_;
|
||||
bool stop_;
|
||||
HANDLE thread_;
|
||||
const std::string name_;
|
||||
rtc::ThreadChecker main_thread_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WIN_H_
|
@ -1,604 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/atomicops.h"
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/source/trace_win.h"
|
||||
#else
|
||||
#include "webrtc/system_wrappers/source/trace_posix.h"
|
||||
#endif // _WIN32
|
||||
|
||||
#define KEY_LEN_CHARS 31
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable:4355)
|
||||
#endif // _WIN32
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int Trace::kBoilerplateLength = 71;
|
||||
const int Trace::kTimestampPosition = 13;
|
||||
const int Trace::kTimestampLength = 12;
|
||||
volatile int Trace::level_filter_ = kTraceDefault;
|
||||
|
||||
// Construct On First Use idiom. Avoids "static initialization order fiasco".
|
||||
TraceImpl* TraceImpl::StaticInstance(CountOperation count_operation,
|
||||
const TraceLevel level) {
|
||||
// Sanities to avoid taking lock unless absolutely necessary (for
|
||||
// performance reasons). count_operation == kAddRefNoCreate implies that a
|
||||
// message will be written to file.
|
||||
if ((level != kTraceAll) && (count_operation == kAddRefNoCreate)) {
|
||||
if (!(level & level_filter())) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
TraceImpl* impl =
|
||||
GetStaticInstance<TraceImpl>(count_operation);
|
||||
return impl;
|
||||
}
|
||||
|
||||
TraceImpl* TraceImpl::GetTrace(const TraceLevel level) {
|
||||
return StaticInstance(kAddRefNoCreate, level);
|
||||
}
|
||||
|
||||
TraceImpl* TraceImpl::CreateInstance() {
|
||||
#if defined(_WIN32)
|
||||
return new TraceWindows();
|
||||
#else
|
||||
return new TracePosix();
|
||||
#endif
|
||||
}
|
||||
|
||||
TraceImpl::TraceImpl()
|
||||
: callback_(NULL),
|
||||
row_count_text_(0),
|
||||
file_count_text_(0),
|
||||
trace_file_(FileWrapper::Create()) {
|
||||
}
|
||||
|
||||
TraceImpl::~TraceImpl() {
|
||||
trace_file_->Flush();
|
||||
trace_file_->CloseFile();
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddThreadId(char* trace_message) const {
|
||||
uint32_t thread_id = ThreadWrapper::GetThreadId();
|
||||
// Messages is 12 characters.
|
||||
return sprintf(trace_message, "%10u; ", thread_id);
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddLevel(char* sz_message, const TraceLevel level) const {
|
||||
const int kMessageLength = 12;
|
||||
switch (level) {
|
||||
case kTraceTerseInfo:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(sz_message, ' ', kMessageLength);
|
||||
sz_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceStateInfo:
|
||||
sprintf(sz_message, "STATEINFO ; ");
|
||||
break;
|
||||
case kTraceWarning:
|
||||
sprintf(sz_message, "WARNING ; ");
|
||||
break;
|
||||
case kTraceError:
|
||||
sprintf(sz_message, "ERROR ; ");
|
||||
break;
|
||||
case kTraceCritical:
|
||||
sprintf(sz_message, "CRITICAL ; ");
|
||||
break;
|
||||
case kTraceInfo:
|
||||
sprintf(sz_message, "DEBUGINFO ; ");
|
||||
break;
|
||||
case kTraceModuleCall:
|
||||
sprintf(sz_message, "MODULECALL; ");
|
||||
break;
|
||||
case kTraceMemory:
|
||||
sprintf(sz_message, "MEMORY ; ");
|
||||
break;
|
||||
case kTraceTimer:
|
||||
sprintf(sz_message, "TIMER ; ");
|
||||
break;
|
||||
case kTraceStream:
|
||||
sprintf(sz_message, "STREAM ; ");
|
||||
break;
|
||||
case kTraceApiCall:
|
||||
sprintf(sz_message, "APICALL ; ");
|
||||
break;
|
||||
case kTraceDebug:
|
||||
sprintf(sz_message, "DEBUG ; ");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
// All messages are 12 characters.
|
||||
return kMessageLength;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddModuleAndId(char* trace_message,
|
||||
const TraceModule module,
|
||||
const int32_t id) const {
|
||||
// Use long int to prevent problems with different definitions of
|
||||
// int32_t.
|
||||
// TODO(hellner): is this actually a problem? If so, it should be better to
|
||||
// clean up int32_t
|
||||
const long int idl = id;
|
||||
const int kMessageLength = 25;
|
||||
if (idl != -1) {
|
||||
const unsigned long int id_engine = id >> 16;
|
||||
const unsigned long int id_channel = id & 0xffff;
|
||||
|
||||
switch (module) {
|
||||
case kTraceUndefined:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(trace_message, ' ', kMessageLength);
|
||||
trace_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceVoice:
|
||||
sprintf(trace_message, " VOICE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf(trace_message, " VIDEO:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf(trace_message, " UTILITY:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf(trace_message, " RTP/RTCP:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf(trace_message, " TRANSPORT:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf(trace_message, "AUDIO CODING:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf(trace_message, " SRTP:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf(trace_message, " AUDIO MIX/S:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf(trace_message, " AUDIO MIX/C:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf(trace_message, "VIDEO CODING:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
// Print sleep time and API call
|
||||
sprintf(trace_message, " VIDEO MIX:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf(trace_message, " FILE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioProcessing:
|
||||
sprintf(trace_message, " AUDIO PROC:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf(trace_message, "AUDIO DEVICE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf(trace_message, "VIDEO RENDER:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf(trace_message, "VIDEO CAPTUR:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
case kTraceRemoteBitrateEstimator:
|
||||
sprintf(trace_message, " BWE RBE:%5ld %5ld;", id_engine,
|
||||
id_channel);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (module) {
|
||||
case kTraceUndefined:
|
||||
// Add the appropriate amount of whitespace.
|
||||
memset(trace_message, ' ', kMessageLength);
|
||||
trace_message[kMessageLength] = '\0';
|
||||
break;
|
||||
case kTraceVoice:
|
||||
sprintf(trace_message, " VOICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf(trace_message, " VIDEO:%11ld;", idl);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf(trace_message, " UTILITY:%11ld;", idl);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf(trace_message, " RTP/RTCP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf(trace_message, " TRANSPORT:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf(trace_message, "AUDIO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf(trace_message, " SRTP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf(trace_message, " AUDIO MIX/S:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf(trace_message, " AUDIO MIX/C:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf(trace_message, "VIDEO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
sprintf(trace_message, " VIDEO MIX:%11ld;", idl);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf(trace_message, " FILE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioProcessing:
|
||||
sprintf(trace_message, " AUDIO PROC:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf(trace_message, "AUDIO DEVICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf(trace_message, "VIDEO RENDER:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf(trace_message, "VIDEO CAPTUR:%11ld;", idl);
|
||||
break;
|
||||
case kTraceRemoteBitrateEstimator:
|
||||
sprintf(trace_message, " BWE RBE:%11ld;", idl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return kMessageLength;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::SetTraceFileImpl(const char* file_name_utf8,
|
||||
const bool add_file_counter) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
|
||||
trace_file_->Flush();
|
||||
trace_file_->CloseFile();
|
||||
|
||||
if (file_name_utf8) {
|
||||
if (add_file_counter) {
|
||||
file_count_text_ = 1;
|
||||
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize];
|
||||
CreateFileName(file_name_utf8, file_name_with_counter_utf8,
|
||||
file_count_text_);
|
||||
if (trace_file_->OpenFile(file_name_with_counter_utf8, false, false,
|
||||
true) == -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
file_count_text_ = 0;
|
||||
if (trace_file_->OpenFile(file_name_utf8, false, false, true) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
row_count_text_ = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::TraceFileImpl(
|
||||
char file_name_utf8[FileWrapper::kMaxFileNameSize]) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
return trace_file_->FileName(file_name_utf8, FileWrapper::kMaxFileNameSize);
|
||||
}
|
||||
|
||||
int32_t TraceImpl::SetTraceCallbackImpl(TraceCallback* callback) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
callback_ = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t TraceImpl::AddMessage(
|
||||
char* trace_message,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t written_so_far) const {
|
||||
int length = 0;
|
||||
if (written_so_far >= WEBRTC_TRACE_MAX_MESSAGE_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
// - 2 to leave room for newline and NULL termination.
|
||||
#ifdef _WIN32
|
||||
length = _snprintf(trace_message,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2,
|
||||
"%s", msg);
|
||||
if (length < 0) {
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2;
|
||||
trace_message[length] = 0;
|
||||
}
|
||||
#else
|
||||
length = snprintf(trace_message,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2,
|
||||
"%s", msg);
|
||||
if (length < 0 ||
|
||||
length > WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2) {
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - written_so_far - 2;
|
||||
trace_message[length] = 0;
|
||||
}
|
||||
#endif
|
||||
// Length with NULL termination.
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
void TraceImpl::AddMessageToList(
|
||||
const char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t length,
|
||||
const TraceLevel level) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
if (callback_)
|
||||
callback_->Print(level, trace_message, length);
|
||||
WriteToFile(trace_message, length);
|
||||
}
|
||||
|
||||
void TraceImpl::WriteToFile(const char* msg, uint16_t length) {
|
||||
if (!trace_file_->Open())
|
||||
return;
|
||||
|
||||
if (row_count_text_ > WEBRTC_TRACE_MAX_FILE_SIZE) {
|
||||
// wrap file
|
||||
row_count_text_ = 0;
|
||||
trace_file_->Flush();
|
||||
|
||||
if (file_count_text_ == 0) {
|
||||
trace_file_->Rewind();
|
||||
} else {
|
||||
char old_file_name[FileWrapper::kMaxFileNameSize];
|
||||
char new_file_name[FileWrapper::kMaxFileNameSize];
|
||||
|
||||
// get current name
|
||||
trace_file_->FileName(old_file_name, FileWrapper::kMaxFileNameSize);
|
||||
trace_file_->CloseFile();
|
||||
|
||||
file_count_text_++;
|
||||
|
||||
UpdateFileName(old_file_name, new_file_name, file_count_text_);
|
||||
|
||||
if (trace_file_->OpenFile(new_file_name, false, false, true) == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row_count_text_ == 0) {
|
||||
char message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
|
||||
int32_t length = AddDateTimeInfo(message);
|
||||
if (length != -1) {
|
||||
message[length] = 0;
|
||||
message[length - 1] = '\n';
|
||||
trace_file_->Write(message, length);
|
||||
row_count_text_++;
|
||||
}
|
||||
}
|
||||
|
||||
char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
memcpy(trace_message, msg, length);
|
||||
trace_message[length] = 0;
|
||||
trace_message[length - 1] = '\n';
|
||||
trace_file_->Write(trace_message, length);
|
||||
row_count_text_++;
|
||||
}
|
||||
|
||||
void TraceImpl::AddImpl(const TraceLevel level,
|
||||
const TraceModule module,
|
||||
const int32_t id,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE]) {
|
||||
if (!TraceCheck(level))
|
||||
return;
|
||||
|
||||
char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* message_ptr = &trace_message[0];
|
||||
int32_t len = AddLevel(message_ptr, level);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
int32_t ack_len = len;
|
||||
|
||||
len = AddTime(message_ptr, level);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddModuleAndId(message_ptr, module, id);
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddThreadId(message_ptr);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
message_ptr += len;
|
||||
ack_len += len;
|
||||
|
||||
len = AddMessage(message_ptr, msg, static_cast<uint16_t>(ack_len));
|
||||
if (len == -1)
|
||||
return;
|
||||
|
||||
ack_len += len;
|
||||
AddMessageToList(trace_message, static_cast<uint16_t>(ack_len), level);
|
||||
}
|
||||
|
||||
bool TraceImpl::TraceCheck(const TraceLevel level) const {
|
||||
return (level & level_filter()) ? true : false;
|
||||
}
|
||||
|
||||
bool TraceImpl::UpdateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const {
|
||||
int32_t length = (int32_t)strlen(file_name_utf8);
|
||||
if (length < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t length_without_file_ending = length - 1;
|
||||
while (length_without_file_ending > 0) {
|
||||
if (file_name_utf8[length_without_file_ending] == '.') {
|
||||
break;
|
||||
} else {
|
||||
length_without_file_ending--;
|
||||
}
|
||||
}
|
||||
if (length_without_file_ending == 0) {
|
||||
length_without_file_ending = length;
|
||||
}
|
||||
int32_t length_to_ = length_without_file_ending - 1;
|
||||
while (length_to_ > 0) {
|
||||
if (file_name_utf8[length_to_] == '_') {
|
||||
break;
|
||||
} else {
|
||||
length_to_--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(file_name_with_counter_utf8, file_name_utf8, length_to_);
|
||||
sprintf(file_name_with_counter_utf8 + length_to_, "_%lu%s",
|
||||
static_cast<long unsigned int>(new_count),
|
||||
file_name_utf8 + length_without_file_ending);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceImpl::CreateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const {
|
||||
int32_t length = (int32_t)strlen(file_name_utf8);
|
||||
if (length < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t length_without_file_ending = length - 1;
|
||||
while (length_without_file_ending > 0) {
|
||||
if (file_name_utf8[length_without_file_ending] == '.') {
|
||||
break;
|
||||
} else {
|
||||
length_without_file_ending--;
|
||||
}
|
||||
}
|
||||
if (length_without_file_ending == 0) {
|
||||
length_without_file_ending = length;
|
||||
}
|
||||
memcpy(file_name_with_counter_utf8, file_name_utf8,
|
||||
length_without_file_ending);
|
||||
sprintf(file_name_with_counter_utf8 + length_without_file_ending, "_%lu%s",
|
||||
static_cast<long unsigned int>(new_count),
|
||||
file_name_utf8 + length_without_file_ending);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::CreateTrace() {
|
||||
TraceImpl::StaticInstance(kAddRef);
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::ReturnTrace() {
|
||||
TraceImpl::StaticInstance(kRelease);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t Trace::TraceFile(char file_name[FileWrapper::kMaxFileNameSize]) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->TraceFileImpl(file_name);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// static
|
||||
void Trace::set_level_filter(int filter) {
|
||||
rtc::AtomicOps::ReleaseStore(&level_filter_, filter);
|
||||
}
|
||||
|
||||
// static
|
||||
int Trace::level_filter() {
|
||||
return rtc::AtomicOps::AcquireLoad(&level_filter_);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t Trace::SetTraceFile(const char* file_name,
|
||||
const bool add_file_counter) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->SetTraceFileImpl(file_name, add_file_counter);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t Trace::SetTraceCallback(TraceCallback* callback) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if (trace) {
|
||||
int ret_val = trace->SetTraceCallbackImpl(callback);
|
||||
ReturnTrace();
|
||||
return ret_val;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Trace::Add(const TraceLevel level, const TraceModule module,
|
||||
const int32_t id, const char* msg, ...) {
|
||||
TraceImpl* trace = TraceImpl::GetTrace(level);
|
||||
if (trace) {
|
||||
if (trace->TraceCheck(level)) {
|
||||
char temp_buff[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* buff = 0;
|
||||
if (msg) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
#ifdef _WIN32
|
||||
_vsnprintf(temp_buff, WEBRTC_TRACE_MAX_MESSAGE_SIZE - 1, msg, args);
|
||||
#else
|
||||
vsnprintf(temp_buff, WEBRTC_TRACE_MAX_MESSAGE_SIZE - 1, msg, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
buff = temp_buff;
|
||||
}
|
||||
trace->AddImpl(level, module, id, buff);
|
||||
}
|
||||
ReturnTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/static_instance.h"
|
||||
#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#define WEBRTC_TRACE_MAX_MESSAGE_SIZE 1024
|
||||
// Total buffer size is WEBRTC_TRACE_NUM_ARRAY (number of buffer partitions) *
|
||||
// WEBRTC_TRACE_MAX_QUEUE (number of lines per buffer partition) *
|
||||
// WEBRTC_TRACE_MAX_MESSAGE_SIZE (number of 1 byte charachters per line) =
|
||||
// 1 or 4 Mbyte.
|
||||
|
||||
#define WEBRTC_TRACE_MAX_FILE_SIZE 100*1000
|
||||
// Number of rows that may be written to file. On average 110 bytes per row (max
|
||||
// 256 bytes per row). So on average 110*100*1000 = 11 Mbyte, max 256*100*1000 =
|
||||
// 25.6 Mbyte
|
||||
|
||||
class TraceImpl : public Trace {
|
||||
public:
|
||||
virtual ~TraceImpl();
|
||||
|
||||
static TraceImpl* CreateInstance();
|
||||
static TraceImpl* GetTrace(const TraceLevel level = kTraceAll);
|
||||
|
||||
int32_t SetTraceFileImpl(const char* file_name, const bool add_file_counter);
|
||||
int32_t TraceFileImpl(char file_name[FileWrapper::kMaxFileNameSize]);
|
||||
|
||||
int32_t SetTraceCallbackImpl(TraceCallback* callback);
|
||||
|
||||
void AddImpl(const TraceLevel level, const TraceModule module,
|
||||
const int32_t id, const char* msg);
|
||||
|
||||
bool TraceCheck(const TraceLevel level) const;
|
||||
|
||||
protected:
|
||||
TraceImpl();
|
||||
|
||||
static TraceImpl* StaticInstance(CountOperation count_operation,
|
||||
const TraceLevel level = kTraceAll);
|
||||
|
||||
int32_t AddThreadId(char* trace_message) const;
|
||||
|
||||
// OS specific implementations.
|
||||
virtual int32_t AddTime(char* trace_message,
|
||||
const TraceLevel level) const = 0;
|
||||
|
||||
virtual int32_t AddDateTimeInfo(char* trace_message) const = 0;
|
||||
|
||||
private:
|
||||
friend class Trace;
|
||||
|
||||
int32_t AddLevel(char* sz_message, const TraceLevel level) const;
|
||||
|
||||
int32_t AddModuleAndId(char* trace_message, const TraceModule module,
|
||||
const int32_t id) const;
|
||||
|
||||
int32_t AddMessage(char* trace_message,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t written_so_far) const;
|
||||
|
||||
void AddMessageToList(
|
||||
const char trace_message[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const uint16_t length,
|
||||
const TraceLevel level);
|
||||
|
||||
bool UpdateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const;
|
||||
|
||||
bool CreateFileName(
|
||||
const char file_name_utf8[FileWrapper::kMaxFileNameSize],
|
||||
char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize],
|
||||
const uint32_t new_count) const;
|
||||
|
||||
void WriteToFile(const char* msg, uint16_t length)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
TraceCallback* callback_ GUARDED_BY(crit_);
|
||||
uint32_t row_count_text_ GUARDED_BY(crit_);
|
||||
uint32_t file_count_text_ GUARDED_BY(crit_);
|
||||
|
||||
const rtc::scoped_ptr<FileWrapper> trace_file_ GUARDED_BY(crit_);
|
||||
rtc::CriticalSection crit_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_posix.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TracePosix::TracePosix()
|
||||
: crit_sect_(*CriticalSectionWrapper::CreateCriticalSection()) {
|
||||
struct timeval system_time_high_res;
|
||||
gettimeofday(&system_time_high_res, 0);
|
||||
prev_api_tick_count_ = prev_tick_count_ = system_time_high_res.tv_sec;
|
||||
}
|
||||
|
||||
TracePosix::~TracePosix() {
|
||||
delete &crit_sect_;
|
||||
}
|
||||
|
||||
int32_t TracePosix::AddTime(char* trace_message, const TraceLevel level) const {
|
||||
struct timeval system_time_high_res;
|
||||
if (gettimeofday(&system_time_high_res, 0) == -1) {
|
||||
return -1;
|
||||
}
|
||||
struct tm buffer;
|
||||
const struct tm* system_time =
|
||||
localtime_r(&system_time_high_res.tv_sec, &buffer);
|
||||
|
||||
const uint32_t ms_time = system_time_high_res.tv_usec / 1000;
|
||||
uint32_t prev_tickCount = 0;
|
||||
{
|
||||
CriticalSectionScoped lock(&crit_sect_);
|
||||
if (level == kTraceApiCall) {
|
||||
prev_tickCount = prev_tick_count_;
|
||||
prev_tick_count_ = ms_time;
|
||||
} else {
|
||||
prev_tickCount = prev_api_tick_count_;
|
||||
prev_api_tick_count_ = ms_time;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t dw_delta_time = ms_time - prev_tickCount;
|
||||
if (prev_tickCount == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wraparound or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5lu) ", system_time->tm_hour,
|
||||
system_time->tm_min, system_time->tm_sec, ms_time,
|
||||
static_cast<unsigned long>(dw_delta_time));
|
||||
// Messages are 22 characters.
|
||||
return 22;
|
||||
}
|
||||
|
||||
int32_t TracePosix::AddDateTimeInfo(char* trace_message) const {
|
||||
time_t t;
|
||||
time(&t);
|
||||
char buffer[26]; // man ctime says buffer should have room for >=26 bytes.
|
||||
sprintf(trace_message, "Local Date: %s", ctime_r(&t, buffer));
|
||||
int32_t len = static_cast<int32_t>(strlen(trace_message));
|
||||
|
||||
if ('\n' == trace_message[len - 1]) {
|
||||
trace_message[len - 1] = '\0';
|
||||
--len;
|
||||
}
|
||||
|
||||
// Messages is 12 characters.
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_POSIX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_POSIX_H_
|
||||
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TracePosix : public TraceImpl {
|
||||
public:
|
||||
TracePosix();
|
||||
~TracePosix() override;
|
||||
|
||||
// This method can be called on several different threads different from
|
||||
// the creating thread.
|
||||
int32_t AddTime(char* trace_message, const TraceLevel level) const override;
|
||||
|
||||
int32_t AddDateTimeInfo(char* trace_message) const override;
|
||||
|
||||
private:
|
||||
volatile mutable uint32_t prev_api_tick_count_;
|
||||
volatile mutable uint32_t prev_tick_count_;
|
||||
|
||||
CriticalSectionWrapper& crit_sect_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_POSIX_H_
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_win.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
TraceWindows::TraceWindows()
|
||||
: prev_api_tick_count_(0),
|
||||
prev_tick_count_(0) {
|
||||
}
|
||||
|
||||
TraceWindows::~TraceWindows() {
|
||||
}
|
||||
|
||||
int32_t TraceWindows::AddTime(char* trace_message,
|
||||
const TraceLevel level) const {
|
||||
uint32_t dw_current_time = timeGetTime();
|
||||
SYSTEMTIME system_time;
|
||||
GetSystemTime(&system_time);
|
||||
|
||||
if (level == kTraceApiCall) {
|
||||
uint32_t dw_delta_time = dw_current_time - prev_tick_count_;
|
||||
prev_tick_count_ = dw_current_time;
|
||||
|
||||
if (prev_tick_count_ == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wrap-around or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5u) ", system_time.wHour,
|
||||
system_time.wMinute, system_time.wSecond,
|
||||
system_time.wMilliseconds, dw_delta_time);
|
||||
} else {
|
||||
uint32_t dw_delta_time = dw_current_time - prev_api_tick_count_;
|
||||
prev_api_tick_count_ = dw_current_time;
|
||||
|
||||
if (prev_api_tick_count_ == 0) {
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 0x0fffffff) {
|
||||
// Either wraparound or data race.
|
||||
dw_delta_time = 0;
|
||||
}
|
||||
if (dw_delta_time > 99999) {
|
||||
dw_delta_time = 99999;
|
||||
}
|
||||
sprintf(trace_message, "(%2u:%2u:%2u:%3u |%5u) ", system_time.wHour,
|
||||
system_time.wMinute, system_time.wSecond,
|
||||
system_time.wMilliseconds, dw_delta_time);
|
||||
}
|
||||
return 22;
|
||||
}
|
||||
|
||||
int32_t TraceWindows::AddDateTimeInfo(char* trace_message) const {
|
||||
prev_api_tick_count_ = timeGetTime();
|
||||
prev_tick_count_ = prev_api_tick_count_;
|
||||
|
||||
SYSTEMTIME sys_time;
|
||||
GetLocalTime(&sys_time);
|
||||
|
||||
TCHAR sz_date_str[20];
|
||||
TCHAR sz_time_str[20];
|
||||
|
||||
// Create date string (e.g. Apr 04 2002)
|
||||
GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &sys_time, TEXT("MMM dd yyyy"),
|
||||
sz_date_str, 20);
|
||||
|
||||
// Create time string (e.g. 15:32:08)
|
||||
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &sys_time, TEXT("HH':'mm':'ss"),
|
||||
sz_time_str, 20);
|
||||
|
||||
sprintf(trace_message, "Local Date: %ls Local Time: %ls", sz_date_str,
|
||||
sz_time_str);
|
||||
|
||||
// Include NULL termination (hence + 1).
|
||||
return static_cast<int32_t>(strlen(trace_message) + 1);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "webrtc/system_wrappers/source/trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class TraceWindows : public TraceImpl {
|
||||
public:
|
||||
TraceWindows();
|
||||
virtual ~TraceWindows();
|
||||
|
||||
virtual int32_t AddTime(char* trace_message, const TraceLevel level) const;
|
||||
|
||||
virtual int32_t AddDateTimeInfo(char* trace_message) const;
|
||||
private:
|
||||
volatile mutable uint32_t prev_api_tick_count_;
|
||||
volatile mutable uint32_t prev_tick_count_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WIN_H_
|
Reference in New Issue
Block a user