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