git-svn-id: http://webrtc.googlecode.com/svn/trunk@6 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
278733b2d9
commit
f0779a2582
6
system_wrappers/OWNERS
Normal file
6
system_wrappers/OWNERS
Normal file
@ -0,0 +1,6 @@
|
||||
hellner@google.com
|
||||
pwestin@google.com
|
||||
perkj@google.com
|
||||
henrika@google.com
|
||||
grunell@google.com
|
||||
mflodman@google.com
|
25
system_wrappers/interface/aligned_malloc.h
Normal file
25
system_wrappers/interface/aligned_malloc.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
void* AlignedMalloc(
|
||||
size_t size,
|
||||
size_t alignment);
|
||||
void AlignedFree(
|
||||
void* memBlock);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
55
system_wrappers/interface/atomic32_wrapper.h
Normal file
55
system_wrappers/interface/atomic32_wrapper.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Atomic system independant 32-bit integer.
|
||||
// Note: uses full memory barriers.
|
||||
// Note: assumes 32-bit (or higher) system
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
class Atomic32Impl;
|
||||
class Atomic32Wrapper
|
||||
{
|
||||
public:
|
||||
Atomic32Wrapper(WebRtc_Word32 initialValue = 0);
|
||||
~Atomic32Wrapper();
|
||||
|
||||
// Prefix operator!
|
||||
WebRtc_Word32 operator++();
|
||||
WebRtc_Word32 operator--();
|
||||
|
||||
Atomic32Wrapper& operator=(const Atomic32Wrapper& rhs);
|
||||
Atomic32Wrapper& operator=(WebRtc_Word32 rhs);
|
||||
|
||||
WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
|
||||
WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
|
||||
|
||||
// Sets the value atomically to newValue if the value equals compare value.
|
||||
// The function returns true if the exchange happened.
|
||||
bool CompareExchange(WebRtc_Word32 newValue, WebRtc_Word32 compareValue);
|
||||
WebRtc_Word32 Value() const;
|
||||
private:
|
||||
// Disable the + and - operator since it's unclear what these operations
|
||||
// should do.
|
||||
Atomic32Wrapper operator+(const Atomic32Wrapper& rhs);
|
||||
Atomic32Wrapper operator-(const Atomic32Wrapper& rhs);
|
||||
|
||||
WebRtc_Word32& operator++(int);
|
||||
WebRtc_Word32& operator--(int);
|
||||
|
||||
// Cheshire cat to hide the implementation (faster than
|
||||
// using virtual functions)
|
||||
Atomic32Impl& _impl;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
|
41
system_wrappers/interface/condition_variable_wrapper.h
Normal file
41
system_wrappers/interface/condition_variable_wrapper.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class ConditionVariableWrapper
|
||||
{
|
||||
public:
|
||||
// Factory method, constructor disabled.
|
||||
static ConditionVariableWrapper* CreateConditionVariable();
|
||||
|
||||
virtual ~ConditionVariableWrapper() {}
|
||||
|
||||
// Calling thread will atomically release critSect and wait until next
|
||||
// some other thread calls Wake() or WakeAll().
|
||||
virtual void SleepCS(CriticalSectionWrapper& critSect) = 0;
|
||||
|
||||
// Same as above but with a timeout.
|
||||
virtual bool SleepCS(CriticalSectionWrapper& critSect,
|
||||
unsigned long maxTimeInMS) = 0;
|
||||
|
||||
// Wakes one thread calling SleepCS().
|
||||
virtual void Wake() = 0;
|
||||
|
||||
// Wakes all threads calling SleepCS().
|
||||
virtual void WakeAll() = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONDITION_VARIABLE_WRAPPER_H_
|
50
system_wrappers/interface/constructor_magic.h
Normal file
50
system_wrappers/interface/constructor_magic.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* WebRtc
|
||||
* Copy from third_party/libjingle/source/talk/base/constructormagic.h
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
|
||||
|
||||
#ifndef DISALLOW_ASSIGN
|
||||
#define DISALLOW_ASSIGN(TypeName) \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
DISALLOW_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
#ifndef DISALLOW_EVIL_CONSTRUCTORS
|
||||
// Alternative, less-accurate legacy name.
|
||||
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TypeName)
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
|
34
system_wrappers/interface/cpu_features_wrapper.h
Normal file
34
system_wrappers/interface/cpu_features_wrapper.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// list of features.
|
||||
typedef enum {
|
||||
kSSE2,
|
||||
kSSE3
|
||||
} CPUFeature;
|
||||
|
||||
typedef int (*WebRtc_CPUInfo)(CPUFeature feature);
|
||||
// returns true if the CPU supports the feature.
|
||||
extern WebRtc_CPUInfo WebRtc_GetCPUInfo;
|
||||
// No CPU feature is available => straight C path.
|
||||
extern WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM;
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_
|
51
system_wrappers/interface/cpu_wrapper.h
Normal file
51
system_wrappers/interface/cpu_wrapper.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CpuWrapper
|
||||
{
|
||||
public:
|
||||
static WebRtc_UWord32 DetectNumberOfCores();
|
||||
|
||||
static CpuWrapper* CreateCpu();
|
||||
virtual ~CpuWrapper() {}
|
||||
|
||||
// Returns the average CPU usage for all processors. The CPU usage can be
|
||||
// between and including 0 to 100 (%)
|
||||
virtual WebRtc_Word32 CpuUsage() = 0;
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* processName,
|
||||
WebRtc_UWord32 length) = 0;
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 dwProcessID) = 0;
|
||||
|
||||
// The CPU usage per core is returned in cpu_usage. The CPU can be between
|
||||
// and including 0 to 100 (%)
|
||||
// Note that the pointer passed as cpu_usage is redirected to a local member
|
||||
// of the CPU wrapper.
|
||||
// numCores is the number of cores in the cpu_usage array.
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& numCores,
|
||||
WebRtc_UWord32*& cpu_usage) = 0;
|
||||
|
||||
virtual void Reset() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
protected:
|
||||
CpuWrapper() {}
|
||||
|
||||
private:
|
||||
static WebRtc_UWord32 _numberOfCores;
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
66
system_wrappers/interface/critical_section_wrapper.h
Normal file
66
system_wrappers/interface/critical_section_wrapper.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
||||
|
||||
// If the critical section is heavily contended it may be beneficial to use
|
||||
// read/write locks instead.
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper
|
||||
{
|
||||
public:
|
||||
// Factory method, constructor disabled
|
||||
static CriticalSectionWrapper* CreateCriticalSection();
|
||||
|
||||
virtual ~CriticalSectionWrapper() {}
|
||||
|
||||
// Tries to grab lock, beginning of a critical section. Will wait for the
|
||||
// lock to become available if the grab failed.
|
||||
virtual void Enter() = 0;
|
||||
|
||||
// Returns a grabbed lock, end of critical section.
|
||||
virtual void Leave() = 0;
|
||||
};
|
||||
|
||||
// RAII extension of the critical section. Prevents Enter/Leave missmatches and
|
||||
// provides more compact critical section syntax.
|
||||
class CriticalSectionScoped
|
||||
{
|
||||
public:
|
||||
CriticalSectionScoped(CriticalSectionWrapper& critsec)
|
||||
:
|
||||
_ptrCritSec(&critsec)
|
||||
{
|
||||
_ptrCritSec->Enter();
|
||||
}
|
||||
|
||||
~CriticalSectionScoped()
|
||||
{
|
||||
if (_ptrCritSec)
|
||||
{
|
||||
Leave();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void Leave()
|
||||
{
|
||||
_ptrCritSec->Leave();
|
||||
_ptrCritSec = 0;
|
||||
}
|
||||
|
||||
CriticalSectionWrapper* _ptrCritSec;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_
|
68
system_wrappers/interface/event_wrapper.h
Normal file
68
system_wrappers/interface/event_wrapper.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
enum EventTypeWrapper
|
||||
{
|
||||
kEventSignaled = 1,
|
||||
kEventError = 2,
|
||||
kEventTimeout = 3
|
||||
};
|
||||
|
||||
#define WEBRTC_EVENT_10_SEC 10000
|
||||
#define WEBRTC_EVENT_INFINITE 0xffffffff
|
||||
|
||||
class EventWrapper
|
||||
{
|
||||
public:
|
||||
// Factory method. Constructor disabled.
|
||||
static EventWrapper* Create();
|
||||
virtual ~EventWrapper() {}
|
||||
|
||||
// Releases threads who are calling Wait() and has started waiting. Please
|
||||
// note that a thread calling Wait() will not start waiting immediately.
|
||||
// assumptions to the contrary is a very common source of issues in
|
||||
// multithreaded programming.
|
||||
// Set is sticky in the sense that it will release at least one thread
|
||||
// either immediately or some time in the future.
|
||||
virtual bool Set() = 0;
|
||||
|
||||
// Prevents future Wait() calls from finishing without a new Set() call.
|
||||
virtual bool Reset() = 0;
|
||||
|
||||
// Puts the calling thread into a wait state. The thread may be released
|
||||
// by a Set() call depending on if other threads are waiting and if so on
|
||||
// timing. The thread that was released will call Reset() before leaving
|
||||
// preventing more threads from being released. If multiple threads
|
||||
// are waiting for the same Set(), only one (random) thread is guaranteed to
|
||||
// be released. It is possible that multiple (random) threads are released
|
||||
// Depending on timing.
|
||||
virtual EventTypeWrapper Wait(unsigned long maxTime) = 0;
|
||||
|
||||
// Starts a timer that will call a non-sticky version of Set() either once
|
||||
// or periodically. If the timer is periodic it ensures that there is no
|
||||
// drift over time relative to the system clock.
|
||||
virtual bool StartTimer(bool periodic, unsigned long time) = 0;
|
||||
|
||||
virtual bool StopTimer() = 0;
|
||||
|
||||
// Only implemented on Windows
|
||||
// Returns 1 if a key has been pressed since last call to this function.
|
||||
// -1 indicates failure
|
||||
// 0 indicates no key has been pressed since last call
|
||||
// TODO(hellner) this function does not seem to belong here
|
||||
static int KeyPressed();
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_EVENT_WRAPPER_H_
|
72
system_wrappers/interface/file_wrapper.h
Normal file
72
system_wrappers/interface/file_wrapper.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
||||
|
||||
#include "common_types.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
// Implementation of an InStream and OutStream that can read (exclusive) or
|
||||
// write from/to a file.
|
||||
|
||||
namespace webrtc {
|
||||
class FileWrapper : public InStream, public OutStream
|
||||
{
|
||||
public:
|
||||
enum { kMaxFileNameSize = 1024};
|
||||
enum { kFileMaxTextMessageSize = 1024};
|
||||
|
||||
// Factory method. Constructor disabled.
|
||||
static FileWrapper* Create();
|
||||
|
||||
// Returns true if a file has been opened.
|
||||
virtual bool Open() const = 0;
|
||||
|
||||
// Opens a file in read or write mode, decided by the readOnly parameter.
|
||||
virtual WebRtc_Word32 OpenFile(const WebRtc_Word8* fileNameUTF8,
|
||||
const bool readOnly,
|
||||
const bool loop = false,
|
||||
const bool text = false) = 0;
|
||||
|
||||
virtual WebRtc_Word32 CloseFile() = 0;
|
||||
|
||||
// Limits the file size.
|
||||
virtual WebRtc_Word32 SetMaxFileSize(WebRtc_Word32 bytes) = 0;
|
||||
|
||||
// Flush any pending writes.
|
||||
virtual WebRtc_Word32 Flush() = 0;
|
||||
|
||||
// Returns the opened file's name in fileNameUTF8. size is the allocated
|
||||
// size of fileNameUTF8. The name will be truncated if the size of
|
||||
// fileNameUTF8 is to small.
|
||||
virtual WebRtc_Word32 FileName(WebRtc_Word8* fileNameUTF8,
|
||||
WebRtc_UWord32 size) const = 0;
|
||||
|
||||
// Write text to the opened file. The written text can contain plain text
|
||||
// and text with type specifiers in the same way as sprintf works.
|
||||
virtual WebRtc_Word32 WriteText(const WebRtc_Word8* text, ...) = 0;
|
||||
|
||||
// Reads len number of bytes from buf to file.
|
||||
virtual int Read(void* buf, int len) = 0;
|
||||
|
||||
// Writes len number of bytes to buf from file. Please note that the actual
|
||||
// writing to file may happen some time later. Call flush to force a write
|
||||
// to take affect
|
||||
virtual bool Write(const void *buf,int len) = 0;
|
||||
|
||||
// Rewinds the file to the start. Only available when OpenFile() has been
|
||||
// called with loop argument set to true. Or readOnly argument has been set
|
||||
// to false.
|
||||
virtual int Rewind() = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
|
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file under third_party_mods/chromium directory of
|
||||
// source tree or at
|
||||
// http://src.chromium.org/viewvc/chrome/trunk/src/LICENSE
|
||||
|
||||
// Various inline functions and macros to fix compilation of 32 bit target
|
||||
// on MSVC with /Wp64 flag enabled.
|
||||
|
||||
// The original code can be found here:
|
||||
// http://src.chromium.org/svn/trunk/src/base/fix_wp64.h
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Platform SDK fixes when building with /Wp64 for a 32 bits target.
|
||||
#if !defined(_WIN64) && defined(_Wp64)
|
||||
|
||||
#ifdef InterlockedExchangePointer
|
||||
#undef InterlockedExchangePointer
|
||||
// The problem is that the macro provided for InterlockedExchangePointer() is
|
||||
// doing a (LONG) C-style cast that triggers invariably the warning C4312 when
|
||||
// building on 32 bits.
|
||||
inline void* InterlockedExchangePointer(void* volatile* target, void* value) {
|
||||
return reinterpret_cast<void*>(static_cast<LONG_PTR>(InterlockedExchange(
|
||||
reinterpret_cast<volatile LONG*>(target),
|
||||
static_cast<LONG>(reinterpret_cast<LONG_PTR>(value)))));
|
||||
}
|
||||
#endif // #ifdef InterlockedExchangePointer
|
||||
|
||||
#endif // #if !defined(_WIN64) && defined(_Wp64)
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
|
109
system_wrappers/interface/list_wrapper.h
Normal file
109
system_wrappers/interface/list_wrapper.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_
|
||||
|
||||
#include "constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class ListItem
|
||||
{
|
||||
friend class ListWrapper;
|
||||
|
||||
public:
|
||||
ListItem(const void* ptr);
|
||||
ListItem(const unsigned int item);
|
||||
virtual ~ListItem();
|
||||
void* GetItem() const;
|
||||
unsigned int GetUnsignedItem() const;
|
||||
|
||||
protected:
|
||||
ListItem* next_;
|
||||
ListItem* prev_;
|
||||
|
||||
private:
|
||||
const void* item_ptr_;
|
||||
const unsigned int item_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListItem);
|
||||
};
|
||||
|
||||
class ListWrapper
|
||||
{
|
||||
public:
|
||||
ListWrapper();
|
||||
virtual ~ListWrapper();
|
||||
|
||||
// Returns the number of elements stored in the list.
|
||||
unsigned int GetSize() const;
|
||||
|
||||
// Puts a pointer to anything last in the list.
|
||||
int PushBack(const void* ptr);
|
||||
// Puts a pointer to anything first in the list.
|
||||
int PushFront(const void* ptr);
|
||||
|
||||
// Puts a copy of the specified integer last in the list.
|
||||
int PushBack(const unsigned int item_id);
|
||||
// Puts a copy of the specified integer first in the list.
|
||||
int PushFront(const unsigned int item_id);
|
||||
|
||||
// Pops the first ListItem from the list
|
||||
int PopFront();
|
||||
|
||||
// Pops the last ListItem from the list
|
||||
int PopBack();
|
||||
|
||||
// Returns true if the list is empty
|
||||
bool Empty() const;
|
||||
|
||||
// Returns a pointer to the first ListItem in the list.
|
||||
ListItem* First() const;
|
||||
|
||||
// Returns a pointer to the last ListItem in the list.
|
||||
ListItem* Last() const;
|
||||
|
||||
// Returns a pointer to the ListItem stored after item in the list.
|
||||
ListItem* Next(ListItem* item) const;
|
||||
|
||||
// Returns a pointer to the ListItem stored before item in the list.
|
||||
ListItem* Previous(ListItem* item) const;
|
||||
|
||||
// Removes item from the list.
|
||||
int Erase(ListItem* item);
|
||||
|
||||
// Insert list item after existing_previous_item. Please note that new_item
|
||||
// must be created using new ListItem(). The map will take ownership of
|
||||
// new_item following a successfull insert. If insert fails new_item will
|
||||
// not be released by the List
|
||||
int Insert(ListItem* existing_previous_item,
|
||||
ListItem* new_item);
|
||||
|
||||
// Insert list item before existing_next_item. Please note that new_item
|
||||
// must be created using new ListItem(). The map will take ownership of
|
||||
// new_item following a successfull insert. If insert fails new_item will
|
||||
// not be released by the List
|
||||
int InsertBefore(ListItem* existing_next_item,
|
||||
ListItem* new_item);
|
||||
|
||||
private:
|
||||
void PushBackImpl(ListItem* item);
|
||||
void PushFrontImpl(ListItem* item);
|
||||
|
||||
CriticalSectionWrapper* critical_section_;
|
||||
ListItem* first_;
|
||||
ListItem* last_;
|
||||
unsigned int size_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListWrapper);
|
||||
};
|
||||
} //namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_
|
77
system_wrappers/interface/map_wrapper.h
Normal file
77
system_wrappers/interface/map_wrapper.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_MAP_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_MAP_WRAPPER_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
class MapItem
|
||||
{
|
||||
friend class MapWrapper;
|
||||
|
||||
public:
|
||||
MapItem(int id, void* ptr);
|
||||
virtual ~MapItem();
|
||||
void* GetItem();
|
||||
int GetId();
|
||||
unsigned int GetUnsignedId();
|
||||
void SetItem(void* ptr);
|
||||
|
||||
private:
|
||||
int item_id_;
|
||||
void* item_pointer_;
|
||||
DISALLOW_COPY_AND_ASSIGN(MapItem);
|
||||
};
|
||||
|
||||
class MapWrapper
|
||||
{
|
||||
public:
|
||||
MapWrapper();
|
||||
~MapWrapper();
|
||||
|
||||
// Puts a pointer to anything in the map and associates it with id. Note, id
|
||||
// needs to be unique for all items in the map.
|
||||
int Insert(int id, void* ptr);
|
||||
|
||||
// Removes item from map.
|
||||
int Erase(MapItem* item);
|
||||
|
||||
// Finds item with associated with id and removes it from the map.
|
||||
int Erase(int id);
|
||||
|
||||
// Returns the number of elements stored in the map.
|
||||
int Size() const;
|
||||
|
||||
// Returns a pointer to the first MapItem in the map.
|
||||
MapItem* First() const;
|
||||
|
||||
// Returns a pointer to the last MapItem in the map.
|
||||
MapItem* Last() const;
|
||||
|
||||
// Returns a pointer to the MapItem stored after item in the map.
|
||||
MapItem* Next(MapItem* item) const;
|
||||
|
||||
// Returns a pointer to the MapItem stored before item in the map.
|
||||
MapItem* Previous(MapItem* item) const;
|
||||
|
||||
// Returns a pointer to the MapItem associated with id from the map.
|
||||
MapItem* Find(int id) const;
|
||||
|
||||
private:
|
||||
std::map<int, MapItem*> map_;
|
||||
DISALLOW_COPY_AND_ASSIGN(MapWrapper);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_MAP_WRAPPER_H_
|
76
system_wrappers/interface/rw_lock_wrapper.h
Normal file
76
system_wrappers/interface/rw_lock_wrapper.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
||||
|
||||
// Note, Windows pre-Vista version of RW locks are not supported nativly. For
|
||||
// these OSs regular critical sections have been used to approximate RW lock
|
||||
// functionality and will therefore have worse performance.
|
||||
|
||||
namespace webrtc {
|
||||
class RWLockWrapper
|
||||
{
|
||||
public:
|
||||
static RWLockWrapper* CreateRWLock();
|
||||
virtual ~RWLockWrapper();
|
||||
|
||||
virtual void AcquireLockExclusive() = 0;
|
||||
virtual void ReleaseLockExclusive() = 0;
|
||||
|
||||
virtual void AcquireLockShared() = 0;
|
||||
virtual void ReleaseLockShared() = 0;
|
||||
|
||||
protected:
|
||||
virtual int Init() = 0;
|
||||
};
|
||||
|
||||
// RAII extensions of the RW lock. Prevents Acquire/Release missmatches and
|
||||
// provides more compact locking syntax.
|
||||
class ReadLockScoped
|
||||
{
|
||||
public:
|
||||
ReadLockScoped(RWLockWrapper& rwLock)
|
||||
:
|
||||
_rwLock(rwLock)
|
||||
{
|
||||
_rwLock.AcquireLockShared();
|
||||
}
|
||||
|
||||
~ReadLockScoped()
|
||||
{
|
||||
_rwLock.ReleaseLockShared();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLockWrapper& _rwLock;
|
||||
};
|
||||
|
||||
class WriteLockScoped
|
||||
{
|
||||
public:
|
||||
WriteLockScoped(RWLockWrapper& rwLock)
|
||||
:
|
||||
_rwLock(rwLock)
|
||||
{
|
||||
_rwLock.AcquireLockExclusive();
|
||||
}
|
||||
|
||||
~WriteLockScoped()
|
||||
{
|
||||
_rwLock.ReleaseLockExclusive();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLockWrapper& _rwLock;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_
|
64
system_wrappers/interface/sort.h
Normal file
64
system_wrappers/interface/sort.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Generic unstable sorting routines.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
TYPE_Word8,
|
||||
TYPE_UWord8,
|
||||
TYPE_Word16,
|
||||
TYPE_UWord16,
|
||||
TYPE_Word32,
|
||||
TYPE_UWord32,
|
||||
TYPE_Word64,
|
||||
TYPE_UWord64,
|
||||
TYPE_Float32,
|
||||
TYPE_Float64
|
||||
};
|
||||
// Sorts intrinsic data types.
|
||||
//
|
||||
// data [in/out] A pointer to an array of intrinsic type.
|
||||
// Upon return it will be sorted in ascending order.
|
||||
// numOfElements The number of elements in the array.
|
||||
// dataType Enum corresponding to the type of the array.
|
||||
//
|
||||
// returns 0 on success, -1 on failure.
|
||||
WebRtc_Word32 Sort(void* data, WebRtc_UWord32 numOfElements, Type dataType);
|
||||
|
||||
// Sorts arbitrary data types. This requires an array of intrinsically typed
|
||||
// key values which will be used to sort the data array. There must be a
|
||||
// one-to-one correspondence between data elements and key elements, with
|
||||
// corresponding elements sharing the same position in their respective
|
||||
// arrays.
|
||||
//
|
||||
// data [in/out] A pointer to an array of arbitrary type.
|
||||
// Upon return it will be sorted in ascending order.
|
||||
// key [in] A pointer to an array of keys used to sort the
|
||||
// data array.
|
||||
// numOfElements The number of elements in the arrays.
|
||||
// sizeOfElement The size, in bytes, of the data array.
|
||||
// keyType Enum corresponding to the type of the key array.
|
||||
//
|
||||
// returns 0 on success, -1 on failure.
|
||||
//
|
||||
WebRtc_Word32 KeySort(void* data, void* key, WebRtc_UWord32 numOfElements,
|
||||
WebRtc_UWord32 sizeOfElement, Type keyType);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SORT_H_
|
86
system_wrappers/interface/thread_wrapper.h
Normal file
86
system_wrappers/interface/thread_wrapper.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// System independant wrapper for spawning threads
|
||||
// Note: the spawned thread will loop over the callback function until stopped.
|
||||
// Note: The callback function is expected to return every 2 seconds or more
|
||||
// often.
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
||||
|
||||
namespace webrtc {
|
||||
// Object that will be passed by the spawned thread when it enters the callback
|
||||
// function.
|
||||
#define ThreadObj void*
|
||||
|
||||
// Callback function that the spawned thread will enter once spawned
|
||||
typedef bool(*ThreadRunFunction)(ThreadObj);
|
||||
|
||||
enum ThreadPriority
|
||||
{
|
||||
kLowPriority = 1,
|
||||
kNormalPriority = 2,
|
||||
kHighPriority = 3,
|
||||
kHighestPriority = 4,
|
||||
kRealtimePriority = 5
|
||||
};
|
||||
|
||||
class ThreadWrapper
|
||||
{
|
||||
public:
|
||||
enum {kThreadMaxNameLength = 64};
|
||||
|
||||
virtual ~ThreadWrapper() {};
|
||||
|
||||
// Factory method. Constructor disabled.
|
||||
//
|
||||
// func Pointer to a, by user, specified callback function.
|
||||
// obj Object associated with the thread. Passed in the callback
|
||||
// function.
|
||||
// prio Thread priority. May require root/admin rights.
|
||||
// threadName NULL terminated thread name, will be visable in the Windows
|
||||
// debugger.
|
||||
static ThreadWrapper* CreateThread(ThreadRunFunction func = 0,
|
||||
ThreadObj obj= 0,
|
||||
ThreadPriority prio = kNormalPriority,
|
||||
const char* threadName = 0);
|
||||
|
||||
// Non blocking termination of the spawned thread. Note that it is not safe
|
||||
// to delete this class until the spawned thread has been reclaimed.
|
||||
virtual void SetNotAlive() = 0;
|
||||
|
||||
// Spawns the thread. This will start the triggering of the callback
|
||||
// function.
|
||||
virtual bool Start(unsigned int& id) = 0;
|
||||
|
||||
// Sets the threads CPU affinity. CPUs are listed 0 - (number of CPUs - 1).
|
||||
// The numbers in processorNumbers specify which CPUs are allowed to run the
|
||||
// thread. processorNumbers should not contain any duplicates and elements
|
||||
// should be lower than (number of CPUs - 1). amountOfProcessors should be
|
||||
// equal to the number of processors listed in processorNumbers
|
||||
virtual bool SetAffinity(const int* /*processorNumbers*/,
|
||||
const unsigned int /*amountOfProcessors*/)
|
||||
{return false;}
|
||||
|
||||
// Stops the spawned thread and waits for it to be reclaimed with a timeout
|
||||
// of two seconds. Will return false if the thread was not reclaimed.
|
||||
// Multiple tries to Stop are allowed (e.g. to wait longer than 2 seconds).
|
||||
// It's ok to call Stop() even if the spawned thread has been reclaimed.
|
||||
virtual bool Stop() = 0;
|
||||
|
||||
// Stops the spawned thread dead in its tracks. Will likely result in a
|
||||
// corrupt state. There should be an extremely good reason for even looking
|
||||
// at this function. Can cause many problems deadlock being one of them.
|
||||
virtual bool Shutdown() {return false;}
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
|
304
system_wrappers/interface/tick_util.h
Normal file
304
system_wrappers/interface/tick_util.h
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// System independant wrapper for polling elapsed time in ms and us.
|
||||
// The implementation works in the tick domain which can be mapped over to the
|
||||
// time domain.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#elif WEBRTC_LINUX
|
||||
#include <ctime>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
class TickInterval;
|
||||
|
||||
class TickTime
|
||||
{
|
||||
public:
|
||||
// Current time in the tick domain.
|
||||
static TickTime Now();
|
||||
|
||||
// Now in the time domain in ms.
|
||||
static WebRtc_Word64 MillisecondTimestamp();
|
||||
|
||||
// Now in the time domain in us.
|
||||
static WebRtc_Word64 MicrosecondTimestamp();
|
||||
|
||||
WebRtc_Word64 Ticks() const;
|
||||
|
||||
static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms);
|
||||
|
||||
static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks);
|
||||
|
||||
// Returns a TickTime that is ticks later than the passed TickTime
|
||||
friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks);
|
||||
TickTime& operator+=(const WebRtc_Word64& rhs);
|
||||
|
||||
|
||||
// Returns a TickInterval that is the difference in ticks beween rhs and lhs
|
||||
friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
|
||||
private:
|
||||
WebRtc_Word64 _ticks;
|
||||
};
|
||||
|
||||
class TickInterval
|
||||
{
|
||||
public:
|
||||
TickInterval();
|
||||
|
||||
WebRtc_Word64 Milliseconds() const;
|
||||
WebRtc_Word64 Microseconds() const;
|
||||
|
||||
// Returns the sum of two TickIntervals as a TickInterval
|
||||
friend TickInterval operator+(const TickInterval& lhs,
|
||||
const TickInterval& rhs);
|
||||
TickInterval& operator-=(const TickInterval& rhs);
|
||||
|
||||
// Returns a TickInterval corresponding to rhs - lhs
|
||||
friend TickInterval operator-(const TickInterval& lhs,
|
||||
const TickInterval& rhs);
|
||||
TickInterval& operator+=(const TickInterval& rhs);
|
||||
|
||||
private:
|
||||
TickInterval(WebRtc_Word64 interval);
|
||||
|
||||
friend class TickTime;
|
||||
friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs);
|
||||
|
||||
private:
|
||||
WebRtc_Word64 _interval;
|
||||
};
|
||||
|
||||
inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs)
|
||||
{
|
||||
return TickInterval(lhs._interval + rhs._interval);
|
||||
}
|
||||
|
||||
inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs)
|
||||
{
|
||||
return TickInterval(lhs._interval - rhs._interval);
|
||||
}
|
||||
|
||||
inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs)
|
||||
{
|
||||
return TickInterval(lhs._ticks - rhs._ticks);
|
||||
}
|
||||
|
||||
inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks)
|
||||
{
|
||||
TickTime time = lhs;
|
||||
time._ticks += ticks;
|
||||
return time;
|
||||
}
|
||||
|
||||
inline TickTime TickTime::Now()
|
||||
{
|
||||
TickTime result;
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
// QueryPerformanceCounter returns the value from the TSC which is
|
||||
// incremented at the CPU frequency. The algorithm used requires
|
||||
// the CPU frequency to be constant. Technology like speed stepping
|
||||
// which has variable CPU frequency will therefore yield unpredictable,
|
||||
// incorrect time estimations.
|
||||
LARGE_INTEGER qpcnt;
|
||||
QueryPerformanceCounter(&qpcnt);
|
||||
result._ticks = qpcnt.QuadPart;
|
||||
#else
|
||||
static volatile LONG lastTimeGetTime = 0;
|
||||
static volatile WebRtc_Word64 numWrapTimeGetTime = 0;
|
||||
volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime;
|
||||
DWORD now = timeGetTime();
|
||||
// Atomically update the last gotten time
|
||||
DWORD old = InterlockedExchange(lastTimeGetTimePtr, now);
|
||||
if(now < old)
|
||||
{
|
||||
// If now is earlier than old, there may have been a race between
|
||||
// threads.
|
||||
// 0x0fffffff ~3.1 days, the code will not take that long to execute
|
||||
// so it must have been a wrap around.
|
||||
if(old > 0xf0000000 && now < 0x0fffffff)
|
||||
{
|
||||
numWrapTimeGetTime++;
|
||||
}
|
||||
}
|
||||
result._ticks = now + (numWrapTimeGetTime<<32);
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
struct timespec ts;
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickTime::MillisecondTimestamp()
|
||||
{
|
||||
TickTime now = TickTime::Now();
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (now._ticks * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
return now._ticks;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
return now._ticks / 1000000LL;
|
||||
#else
|
||||
return now._ticks / 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
|
||||
{
|
||||
TickTime now = TickTime::Now();
|
||||
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (now._ticks * 1000) / (qpfreq.QuadPart/1000);
|
||||
#else
|
||||
return now._ticks *1000LL;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
return now._ticks / 1000LL;
|
||||
#else
|
||||
return now._ticks;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickTime::Ticks() const
|
||||
{
|
||||
return _ticks;
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
|
||||
{
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (qpfreq.QuadPart * ms) / 1000;
|
||||
#else
|
||||
return ms;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
return ms * 1000000LL;
|
||||
#else
|
||||
return ms * 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
|
||||
{
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (ticks * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
return ticks;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
return ticks / 1000000LL;
|
||||
#else
|
||||
return ticks / 1000LL;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks)
|
||||
{
|
||||
_ticks += ticks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TickInterval::TickInterval() : _interval(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline TickInterval::TickInterval(const WebRtc_Word64 interval)
|
||||
: _interval(interval)
|
||||
{
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickInterval::Milliseconds() const
|
||||
{
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (_interval * 1000) / qpfreq.QuadPart;
|
||||
#else
|
||||
// _interval is in ms
|
||||
return _interval;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
// _interval is in ns
|
||||
return _interval / 1000000;
|
||||
#else
|
||||
// _interval is usecs
|
||||
return _interval / 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline WebRtc_Word64 TickInterval::Microseconds() const
|
||||
{
|
||||
#if _WIN32
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
LARGE_INTEGER qpfreq;
|
||||
QueryPerformanceFrequency(&qpfreq);
|
||||
return (_interval * 1000000) / qpfreq.QuadPart;
|
||||
#else
|
||||
// _interval is in ms
|
||||
return _interval *1000LL;
|
||||
#endif
|
||||
#elif WEBRTC_LINUX
|
||||
// _interval is in ns
|
||||
return _interval / 1000;
|
||||
#else
|
||||
// _interval is usecs
|
||||
return _interval;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline TickInterval& TickInterval::operator+=(const TickInterval& rhs)
|
||||
{
|
||||
_interval += rhs._interval;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TickInterval& TickInterval::operator-=(const TickInterval& rhs)
|
||||
{
|
||||
_interval -= rhs._interval;
|
||||
return *this;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
83
system_wrappers/interface/trace.h
Normal file
83
system_wrappers/interface/trace.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// System independant wrapper for logging runtime information to file.
|
||||
// Note: All log messages will be written to the same trace file.
|
||||
// Note: If to many messages are written to file there will be a build up of
|
||||
// messages. Apply filtering to avoid that.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
||||
|
||||
#include "common_types.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#ifdef WEBRTC_NO_TRACE
|
||||
#define WEBRTC_TRACE
|
||||
#else
|
||||
// Ideally we would use __VA_ARGS__ but it's not supported by all compilers
|
||||
// such as VS2003 (it's supported in VS2005). TODO (hellner) why
|
||||
// would this be better than current implementation (not convinced)?
|
||||
#define WEBRTC_TRACE Trace::Add
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
|
||||
// Increments the reference count to the trace.
|
||||
static void CreateTrace();
|
||||
// Decrements the reference count to the trace.
|
||||
static void ReturnTrace();
|
||||
// Note: any instance that writes to the trace file should increment and
|
||||
// decrement the reference count on construction and destruction
|
||||
// respectively
|
||||
|
||||
// Specifies what type of messages should be written to the trace file. The
|
||||
// filter parameter is a bitmask where each message type is enumerated by
|
||||
// the TraceLevel enumerator. TODO (hellner) why is the
|
||||
// TraceLevel enumerator not defined in this file?
|
||||
static WebRtc_Word32 SetLevelFilter(const WebRtc_UWord32 filter);
|
||||
|
||||
// Returns what type of messages are written to the trace file.
|
||||
static WebRtc_Word32 LevelFilter(WebRtc_UWord32& filter);
|
||||
|
||||
// Sets the file name. If addFileCounter is false the same file will be
|
||||
// reused when it fills up. If it's true a new file with incremented name
|
||||
// will be used.
|
||||
static WebRtc_Word32 SetTraceFile(const WebRtc_Word8* fileName,
|
||||
const bool addFileCounter = false);
|
||||
|
||||
// Returns the name of the file that the trace is currently writing to.
|
||||
static WebRtc_Word32 TraceFile(WebRtc_Word8 fileName[1024]);
|
||||
|
||||
// Registers callback to receive trace messages. TODO (hellner)
|
||||
// why not use OutStream instead? Why is TraceCallback not defined in this
|
||||
// file
|
||||
static WebRtc_Word32 SetTraceCallback(TraceCallback* callback);
|
||||
|
||||
// Adds a trace message for writing to file. The message is put in a queue
|
||||
// for writing to file whenever possible for performance reasons. I.e. there
|
||||
// is a crash it is possible that the last, vital logs are not logged yet.
|
||||
// level is the the type of message to log. If that type of messages is
|
||||
// filtered it will not be written to file. module is an identifier for what
|
||||
// part of the code the message is comming.
|
||||
// id is an identifier that should be unique for that set of classes that
|
||||
// are associated (e.g. all instances owned by an engine).
|
||||
// msg and the elipsis are the same as e.g. sprintf.
|
||||
// TODO (hellner) Why is TraceModule not defined in this file?
|
||||
static void Add(const TraceLevel level,
|
||||
const TraceModule module,
|
||||
const WebRtc_Word32 id,
|
||||
const char* msg, ...);
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
|
121
system_wrappers/source/aligned_malloc.cc
Normal file
121
system_wrappers/source/aligned_malloc.cc
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 "aligned_malloc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <memory.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if WEBRTC_MAC
|
||||
#include <malloc/malloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
// Ok reference on memory alignment:
|
||||
// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
// TODO (hellner) better to create just one memory block and
|
||||
// interpret the first sizeof(AlignedMemory) bytes as
|
||||
// an AlignedMemory struct.
|
||||
struct AlignedMemory
|
||||
{
|
||||
void* alignedBuffer;
|
||||
void* memoryPointer;
|
||||
};
|
||||
|
||||
void* AlignedMalloc(size_t size, size_t alignment)
|
||||
{
|
||||
if(alignment == 0)
|
||||
{
|
||||
// Don't allow alignment 0 since it's undefined.
|
||||
return NULL;
|
||||
}
|
||||
// Make sure that the alignment is an integer power of two or fail.
|
||||
if(alignment & (alignment - 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AlignedMemory* returnValue = new AlignedMemory();
|
||||
if(returnValue == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The memory is aligned towards the lowest address that so only
|
||||
// alignment - 1 bytes needs to be allocated.
|
||||
// A pointer to AlignedMemory must be stored so that it can be retreived for
|
||||
// deletion, ergo the sizeof(uintptr_t).
|
||||
returnValue->memoryPointer = malloc(size + sizeof(uintptr_t) +
|
||||
alignment - 1);
|
||||
if(returnValue->memoryPointer == NULL)
|
||||
{
|
||||
delete returnValue;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Alligning after the sizeof(header) bytes will leave room for the header
|
||||
// in the same memory block.
|
||||
uintptr_t alignStartPos = (uintptr_t)returnValue->memoryPointer;
|
||||
alignStartPos += sizeof(uintptr_t);
|
||||
|
||||
// The buffer should be aligned with 'alignment' bytes. The - 1 guarantees
|
||||
// that we align towards the lowest address.
|
||||
uintptr_t alignedPos = (alignStartPos + alignment - 1) & ~(alignment - 1);
|
||||
|
||||
// alignedPos is the address sought for.
|
||||
returnValue->alignedBuffer = (void*)alignedPos;
|
||||
|
||||
// Store the address to the AlignedMemory struct in the header so that a
|
||||
// it's possible to reclaim all memory.
|
||||
uintptr_t headerPos = alignedPos;
|
||||
headerPos -= sizeof(uintptr_t);
|
||||
void* headerPtr = (void*) headerPos;
|
||||
uintptr_t headerValue = (uintptr_t)returnValue;
|
||||
memcpy(headerPtr,&headerValue,sizeof(uintptr_t));
|
||||
|
||||
return returnValue->alignedBuffer;
|
||||
}
|
||||
|
||||
void AlignedFree(void* memBlock)
|
||||
{
|
||||
if(memBlock == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uintptr_t alignedPos = (uintptr_t)memBlock;
|
||||
uintptr_t headerPos = alignedPos - sizeof(uintptr_t);
|
||||
|
||||
// Read out the address of the AlignedMemory struct from the header.
|
||||
uintptr_t* headerPtr = (uintptr_t*)headerPos;
|
||||
AlignedMemory* deleteMemory = (AlignedMemory*) *headerPtr;
|
||||
|
||||
if(deleteMemory->memoryPointer != NULL)
|
||||
{
|
||||
free(deleteMemory->memoryPointer);
|
||||
}
|
||||
delete deleteMemory;
|
||||
}
|
||||
} // namespace webrtc
|
84
system_wrappers/source/atomic32.cc
Normal file
84
system_wrappers/source/atomic32.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 "atomic32_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "atomic32_windows.h"
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
#include "atomic32_linux.h"
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include "atomic32_mac.h"
|
||||
#else
|
||||
#error unsupported os!
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
Atomic32Wrapper::Atomic32Wrapper(WebRtc_Word32 initialValue)
|
||||
: _impl(*new Atomic32Impl(initialValue))
|
||||
{
|
||||
}
|
||||
|
||||
Atomic32Wrapper::~Atomic32Wrapper()
|
||||
{
|
||||
delete &_impl;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Atomic32Wrapper::operator++()
|
||||
{
|
||||
return ++_impl;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Atomic32Wrapper::operator--()
|
||||
{
|
||||
return --_impl;
|
||||
}
|
||||
|
||||
// Read and write to properly aligned variables are atomic operations.
|
||||
// Ex reference (for Windows): http://msdn.microsoft.com/en-us/library/ms684122(v=VS.85).aspx
|
||||
// TODO (hellner) operator= and Atomic32Wrapper::Value() can be fully
|
||||
// implemented here.
|
||||
Atomic32Wrapper& Atomic32Wrapper::operator=(const Atomic32Wrapper& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
_impl = rhs._impl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Atomic32Wrapper& Atomic32Wrapper::operator=(WebRtc_Word32 rhs)
|
||||
{
|
||||
_impl = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Atomic32Wrapper::operator+=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return _impl += rhs;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Atomic32Wrapper::operator-=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return _impl -= rhs;
|
||||
}
|
||||
|
||||
bool Atomic32Wrapper::CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue)
|
||||
{
|
||||
return _impl.CompareExchange(newValue,compareValue);
|
||||
}
|
||||
|
||||
WebRtc_Word32 Atomic32Wrapper::Value() const
|
||||
{
|
||||
return _impl.Value();
|
||||
}
|
||||
} // namespace webrtc
|
119
system_wrappers/source/atomic32_linux.h
Normal file
119
system_wrappers/source/atomic32_linux.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Atomic system independant 32-bit signed integer.
|
||||
// Linux implementation.
|
||||
// Note: Requires gcc 4.1.2 or later.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
class Atomic32Impl
|
||||
{
|
||||
public:
|
||||
inline Atomic32Impl(WebRtc_Word32 initialValue);
|
||||
inline ~Atomic32Impl();
|
||||
|
||||
inline WebRtc_Word32 operator++();
|
||||
inline WebRtc_Word32 operator--();
|
||||
|
||||
inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
|
||||
inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
|
||||
|
||||
inline bool CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue);
|
||||
|
||||
inline WebRtc_Word32 Value() const;
|
||||
private:
|
||||
void* _ptrMemory;
|
||||
// Volatile ensures full memory barriers.
|
||||
volatile WebRtc_Word32* _value;
|
||||
};
|
||||
|
||||
// TODO (hellner) use aligned_malloc instead of doing it manually.
|
||||
inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
|
||||
: _ptrMemory(NULL),
|
||||
_value(NULL)
|
||||
{ // Align the memory associated with _value on a 32-bit boundary. This is a
|
||||
// requirement for the used Linux APIs to be atomic.
|
||||
// Keep _ptrMemory to be able to reclaim memory.
|
||||
_ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
|
||||
_value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
|
||||
*_value = initialValue;
|
||||
}
|
||||
|
||||
inline Atomic32Impl::~Atomic32Impl()
|
||||
{
|
||||
if(_ptrMemory != NULL)
|
||||
{
|
||||
free(_ptrMemory);
|
||||
}
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator++()
|
||||
{
|
||||
WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,1);
|
||||
returnValue++;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator--()
|
||||
{
|
||||
WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,1);
|
||||
returnValue--;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
|
||||
{
|
||||
*_value = *rhs._value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
|
||||
{
|
||||
*_value = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
|
||||
{
|
||||
WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,rhs);
|
||||
returnValue += rhs;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
|
||||
{
|
||||
WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,rhs);
|
||||
returnValue -= rhs;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(_value,compareValue,newValue);
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::Value() const
|
||||
{
|
||||
return *_value;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
|
117
system_wrappers/source/atomic32_mac.h
Normal file
117
system_wrappers/source/atomic32_mac.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Atomic system independant 32-bit signed integer.
|
||||
// Mac implementation.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
class Atomic32Impl
|
||||
{
|
||||
public:
|
||||
inline Atomic32Impl(WebRtc_Word32 initialValue);
|
||||
inline ~Atomic32Impl();
|
||||
|
||||
inline WebRtc_Word32 operator++();
|
||||
inline WebRtc_Word32 operator--();
|
||||
|
||||
inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
|
||||
inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
|
||||
|
||||
inline bool CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue);
|
||||
|
||||
inline WebRtc_Word32 Value() const;
|
||||
private:
|
||||
void* _ptrMemory;
|
||||
// Volatile ensures full memory barriers.
|
||||
volatile WebRtc_Word32* _value;
|
||||
};
|
||||
|
||||
// TODO (hellner) use aligned_malloc instead of doing it manually.
|
||||
inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
|
||||
:
|
||||
_ptrMemory(NULL),
|
||||
_value(NULL)
|
||||
{ // Align the memory associated with _value on a 32-bit boundary. This is a
|
||||
// requirement for the used Mac APIs to be atomic.
|
||||
// Keep _ptrMemory to be able to reclaim memory.
|
||||
_ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
|
||||
_value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
|
||||
*_value = initialValue;
|
||||
}
|
||||
|
||||
inline Atomic32Impl::~Atomic32Impl()
|
||||
{
|
||||
if(_ptrMemory != NULL)
|
||||
{
|
||||
free(_ptrMemory);
|
||||
}
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator++()
|
||||
{
|
||||
return OSAtomicIncrement32Barrier(
|
||||
reinterpret_cast<volatile int32_t*>(_value));
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator--()
|
||||
{
|
||||
return OSAtomicDecrement32Barrier(
|
||||
reinterpret_cast<volatile int32_t*>(_value));
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
|
||||
{
|
||||
*_value = *rhs._value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
|
||||
{
|
||||
*_value = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return OSAtomicAdd32Barrier(rhs,
|
||||
reinterpret_cast<volatile int32_t*>(_value));
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return OSAtomicAdd32Barrier(-rhs,
|
||||
reinterpret_cast<volatile int32_t*>(_value));
|
||||
}
|
||||
|
||||
inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue)
|
||||
{
|
||||
return OSAtomicCompareAndSwap32Barrier(
|
||||
compareValue,
|
||||
newValue,
|
||||
reinterpret_cast<volatile int32_t*>(_value));
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::Value() const
|
||||
{
|
||||
return *_value;
|
||||
}
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
|
113
system_wrappers/source/atomic32_windows.h
Normal file
113
system_wrappers/source/atomic32_windows.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Atomic system independant 32-bit signed integer.
|
||||
// Windows implementation.
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_WINDOWS_H_
|
||||
|
||||
#include <malloc.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
class Atomic32Impl
|
||||
{
|
||||
public:
|
||||
inline Atomic32Impl(WebRtc_Word32 initialValue);
|
||||
inline ~Atomic32Impl();
|
||||
|
||||
inline WebRtc_Word32 operator++();
|
||||
inline WebRtc_Word32 operator--();
|
||||
|
||||
inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
|
||||
inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
|
||||
inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
|
||||
|
||||
inline bool CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue);
|
||||
|
||||
inline WebRtc_Word32 Value() const;
|
||||
private:
|
||||
void* _ptrMemory;
|
||||
// Volatile ensures full memory barriers.
|
||||
volatile LONG* _value;
|
||||
};
|
||||
|
||||
// TODO (hellner) use aligned_malloc instead of doing it manually.
|
||||
inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
|
||||
: _ptrMemory(NULL),
|
||||
_value(NULL)
|
||||
{ // Align the memory associated with _value on a 32-bit boundary. This is a
|
||||
// requirement for the used Windows APIs to be atomic.
|
||||
// Keep _ptrMemory to be able to reclaim memory.
|
||||
_ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
|
||||
_value = reinterpret_cast<LONG*> (((uintptr_t)_ptrMemory+3)&(~0x3));
|
||||
*_value = initialValue;
|
||||
}
|
||||
|
||||
inline Atomic32Impl::~Atomic32Impl()
|
||||
{
|
||||
if(_ptrMemory != NULL)
|
||||
{
|
||||
free(_ptrMemory);
|
||||
}
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator++()
|
||||
{
|
||||
return (WebRtc_Word32)InterlockedIncrement(_value);
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator--()
|
||||
{
|
||||
return (WebRtc_Word32)InterlockedDecrement(_value);
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
|
||||
{
|
||||
*_value = *rhs._value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
|
||||
{
|
||||
*_value = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return InterlockedExchangeAdd(_value,rhs);
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
|
||||
{
|
||||
return InterlockedExchangeAdd(_value,-rhs);
|
||||
}
|
||||
|
||||
inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
|
||||
WebRtc_Word32 compareValue)
|
||||
{
|
||||
const LONG oldValue = InterlockedCompareExchange(_value,newValue,
|
||||
compareValue);
|
||||
// If the old value and the compare value is the same an exchange happened.
|
||||
return (oldValue == compareValue);
|
||||
}
|
||||
|
||||
inline WebRtc_Word32 Atomic32Impl::Value() const
|
||||
{
|
||||
return *_value;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_WINDOWS_H_
|
37
system_wrappers/source/condition_variable.cc
Normal file
37
system_wrappers/source/condition_variable.cc
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 "condition_variable_wrapper.h"
|
||||
#include "condition_variable_windows.h"
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
#include <pthread.h>
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "condition_variable_linux.h"
|
||||
#elif defined(WEBRTC_MAC) || defined(WEBRTC_MAC_INTEL)
|
||||
#include <pthread.h>
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "condition_variable_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
ConditionVariableWrapper*
|
||||
ConditionVariableWrapper::CreateConditionVariable()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return new ConditionVariableWindows;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) || defined(WEBRTC_MAC_INTEL)
|
||||
return ConditionVariableLinux::Create();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
151
system_wrappers/source/condition_variable_linux.cc
Normal file
151
system_wrappers/source/condition_variable_linux.cc
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 "condition_variable_linux.h"
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include <ctime>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "critical_section_linux.h"
|
||||
|
||||
namespace webrtc {
|
||||
ConditionVariableWrapper* ConditionVariableLinux::Create()
|
||||
{
|
||||
ConditionVariableLinux* ptr = new ConditionVariableLinux;
|
||||
if (!ptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int error = ptr->Construct();
|
||||
if (error)
|
||||
{
|
||||
delete ptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ConditionVariableLinux::ConditionVariableLinux()
|
||||
{
|
||||
}
|
||||
|
||||
int ConditionVariableLinux::Construct()
|
||||
{
|
||||
int result = 0;
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
result = pthread_cond_init(&_cond, NULL);
|
||||
#else
|
||||
pthread_condattr_t condAttr;
|
||||
result = pthread_condattr_init(&condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_cond_init(&_cond, &condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_destroy(&condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConditionVariableLinux::~ConditionVariableLinux()
|
||||
{
|
||||
pthread_cond_destroy(&_cond);
|
||||
}
|
||||
|
||||
void ConditionVariableLinux::SleepCS(CriticalSectionWrapper& critSect)
|
||||
{
|
||||
CriticalSectionLinux* cs = reinterpret_cast<CriticalSectionLinux*>(
|
||||
&critSect);
|
||||
pthread_cond_wait(&_cond, &cs->_mutex);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ConditionVariableLinux::SleepCS(
|
||||
CriticalSectionWrapper& critSect,
|
||||
unsigned long maxTimeInMS)
|
||||
{
|
||||
const unsigned long INFINITE = 0xFFFFFFFF;
|
||||
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
#ifndef WEBRTC_LINUX
|
||||
const int MICROSECONDS_PER_MILLISECOND = 1000;
|
||||
#endif
|
||||
const int NANOSECONDS_PER_SECOND = 1000000000;
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
CriticalSectionLinux* cs = reinterpret_cast<CriticalSectionLinux*>(
|
||||
&critSect);
|
||||
|
||||
if (maxTimeInMS != INFINITE)
|
||||
{
|
||||
timespec ts;
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND;
|
||||
#endif
|
||||
|
||||
ts.tv_sec += maxTimeInMS / MILLISECONDS_PER_SECOND;
|
||||
ts.tv_nsec += (maxTimeInMS - ((maxTimeInMS / MILLISECONDS_PER_SECOND)*
|
||||
MILLISECONDS_PER_SECOND)) * NANOSECONDS_PER_MILLISECOND;
|
||||
|
||||
if (ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
const int res = pthread_cond_timedwait(&_cond, &cs->_mutex, &ts);
|
||||
return (res == ETIMEDOUT) ? false : true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_cond_wait(&_cond, &cs->_mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableLinux::Wake()
|
||||
{
|
||||
pthread_cond_signal(&_cond);
|
||||
}
|
||||
|
||||
void ConditionVariableLinux::WakeAll()
|
||||
{
|
||||
pthread_cond_broadcast(&_cond);
|
||||
}
|
||||
} // namespace webrtc
|
39
system_wrappers/source/condition_variable_linux.h
Normal file
39
system_wrappers/source/condition_variable_linux.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_LINUX_H_
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
class ConditionVariableLinux : public ConditionVariableWrapper
|
||||
{
|
||||
public:
|
||||
static ConditionVariableWrapper* Create();
|
||||
~ConditionVariableLinux();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& critSect);
|
||||
bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
ConditionVariableLinux();
|
||||
int Construct();
|
||||
|
||||
private:
|
||||
pthread_cond_t _cond;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_LINUX_H_
|
224
system_wrappers/source/condition_variable_windows.cc
Normal file
224
system_wrappers/source/condition_variable_windows.cc
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Use of this source code is governed by the ACE copyright license which
|
||||
* can be found in the LICENSE file in the third_party_mods/ace directory of
|
||||
* the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html.
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TODO (hellner): probably nicer to split up native and generic
|
||||
// implementation into two different files
|
||||
|
||||
#include "condition_variable_windows.h"
|
||||
|
||||
#include "critical_section_windows.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
bool ConditionVariableWindows::_winSupportConditionVariablesPrimitive = false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
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);
|
||||
|
||||
ConditionVariableWindows::ConditionVariableWindows()
|
||||
: _eventID(WAKEALL_0)
|
||||
{
|
||||
if (!library)
|
||||
{
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if (library)
|
||||
{
|
||||
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");
|
||||
_winSupportConditionVariablesPrimitive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_winSupportConditionVariablesPrimitive)
|
||||
{
|
||||
_PInitializeConditionVariable(&_conditionVariable);
|
||||
|
||||
_events[WAKEALL_0] = NULL;
|
||||
_events[WAKEALL_1] = NULL;
|
||||
_events[WAKE] = NULL;
|
||||
|
||||
} else {
|
||||
memset(&_numWaiters[0],0,sizeof(_numWaiters));
|
||||
|
||||
InitializeCriticalSection(&_numWaitersCritSect);
|
||||
|
||||
_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
|
||||
}
|
||||
}
|
||||
|
||||
ConditionVariableWindows::~ConditionVariableWindows()
|
||||
{
|
||||
if(!_winSupportConditionVariablesPrimitive)
|
||||
{
|
||||
CloseHandle(_events[WAKE]);
|
||||
CloseHandle(_events[WAKEALL_1]);
|
||||
CloseHandle(_events[WAKEALL_0]);
|
||||
|
||||
DeleteCriticalSection(&_numWaitersCritSect);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect)
|
||||
{
|
||||
SleepCS(critSect, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect,
|
||||
unsigned long maxTimeInMS)
|
||||
{
|
||||
CriticalSectionWindows* cs = reinterpret_cast<CriticalSectionWindows*>(
|
||||
&critSect);
|
||||
|
||||
if(_winSupportConditionVariablesPrimitive)
|
||||
{
|
||||
BOOL retVal = _PSleepConditionVariableCS(&_conditionVariable,
|
||||
&(cs->crit),maxTimeInMS);
|
||||
return (retVal == 0) ? false : true;
|
||||
|
||||
}else
|
||||
{
|
||||
EnterCriticalSection(&_numWaitersCritSect);
|
||||
// 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;
|
||||
++(_numWaiters[eventID]);
|
||||
LeaveCriticalSection(&_numWaitersCritSect);
|
||||
|
||||
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.
|
||||
maxTimeInMS);
|
||||
|
||||
const bool retVal = (result != WAIT_TIMEOUT);
|
||||
|
||||
EnterCriticalSection(&_numWaitersCritSect);
|
||||
--(_numWaiters[eventID]);
|
||||
// Last waiter should only be true for WakeAll(). WakeAll() correspond
|
||||
// to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
|
||||
const bool lastWaiter = (result == WAIT_OBJECT_0 + 1) &&
|
||||
(_numWaiters[eventID] == 0);
|
||||
LeaveCriticalSection(&_numWaitersCritSect);
|
||||
|
||||
if (lastWaiter)
|
||||
{
|
||||
// Reset/unset the WakeAll() event since all threads have been
|
||||
// released.
|
||||
ResetEvent(_events[eventID]);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&cs->crit);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConditionVariableWindows::Wake()
|
||||
{
|
||||
if(_winSupportConditionVariablesPrimitive)
|
||||
{
|
||||
_PWakeConditionVariable(&_conditionVariable);
|
||||
}else
|
||||
{
|
||||
EnterCriticalSection(&_numWaitersCritSect);
|
||||
const bool haveWaiters = (_numWaiters[WAKEALL_0] > 0) ||
|
||||
(_numWaiters[WAKEALL_1] > 0);
|
||||
LeaveCriticalSection(&_numWaitersCritSect);
|
||||
|
||||
if (haveWaiters)
|
||||
{
|
||||
SetEvent(_events[WAKE]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConditionVariableWindows::WakeAll()
|
||||
{
|
||||
if(_winSupportConditionVariablesPrimitive)
|
||||
{
|
||||
_PWakeAllConditionVariable(&_conditionVariable);
|
||||
}else
|
||||
{
|
||||
EnterCriticalSection(&_numWaitersCritSect);
|
||||
// Update current WakeAll() event
|
||||
_eventID = (WAKEALL_0 == _eventID) ? WAKEALL_1 : WAKEALL_0;
|
||||
// Trigger current event
|
||||
const EventWakeUpType eventID = _eventID;
|
||||
const bool haveWaiters = _numWaiters[eventID] > 0;
|
||||
LeaveCriticalSection(&_numWaitersCritSect);
|
||||
|
||||
if (haveWaiters)
|
||||
{
|
||||
SetEvent(_events[eventID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
67
system_wrappers/source/condition_variable_windows.h
Normal file
67
system_wrappers/source/condition_variable_windows.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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_CONDITION_VARIABLE_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
|
||||
#include <windows.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 ConditionVariableWindows : public ConditionVariableWrapper
|
||||
{
|
||||
public:
|
||||
ConditionVariableWindows();
|
||||
~ConditionVariableWindows();
|
||||
|
||||
void SleepCS(CriticalSectionWrapper& critSect);
|
||||
bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
|
||||
void Wake();
|
||||
void WakeAll();
|
||||
|
||||
private:
|
||||
enum EventWakeUpType
|
||||
{
|
||||
WAKEALL_0 = 0,
|
||||
WAKEALL_1 = 1,
|
||||
WAKE = 2,
|
||||
EVENT_COUNT = 3
|
||||
};
|
||||
|
||||
private:
|
||||
// Native support for Windows Vista+
|
||||
static bool _winSupportConditionVariablesPrimitive;
|
||||
CONDITION_VARIABLE _conditionVariable;
|
||||
|
||||
unsigned int _numWaiters[2];
|
||||
EventWakeUpType _eventID;
|
||||
CRITICAL_SECTION _numWaitersCritSect;
|
||||
HANDLE _events[EVENT_COUNT];
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
|
87
system_wrappers/source/cpu.cc
Normal file
87
system_wrappers/source/cpu.cc
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 "cpu_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#include "engine_configurations.h"
|
||||
#include "cpu_windows.h"
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include "cpu_mac.h"
|
||||
#elif defined(WEBRTC_MAC_INTEL)
|
||||
#include "cpu_mac.h"
|
||||
#elif defined(ANDROID)
|
||||
// Not implemented yet, might be possible to use Linux implementation
|
||||
#else // defined(WEBRTC_LINUX)
|
||||
#include <sys/sysinfo.h>
|
||||
#include "cpu_linux.h"
|
||||
#endif
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
WebRtc_UWord32 CpuWrapper::_numberOfCores = 0;
|
||||
|
||||
WebRtc_UWord32 CpuWrapper::DetectNumberOfCores()
|
||||
{
|
||||
if (!_numberOfCores)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
_numberOfCores = static_cast<WebRtc_UWord32>(si.dwNumberOfProcessors);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", _numberOfCores);
|
||||
|
||||
#elif defined(WEBRTC_LINUX) && !defined(ANDROID)
|
||||
_numberOfCores = get_nprocs();
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", _numberOfCores);
|
||||
|
||||
#elif (defined(WEBRTC_MAC) || defined(WEBRTC_MAC_INTEL))
|
||||
int name[] = {CTL_HW, HW_AVAILCPU};
|
||||
int ncpu;
|
||||
size_t size = sizeof(ncpu);
|
||||
if(0 == sysctl(name, 2, &ncpu, &size, NULL, 0))
|
||||
{
|
||||
_numberOfCores = static_cast<WebRtc_UWord32>(ncpu);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Available number of cores:%d", _numberOfCores);
|
||||
} else
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
||||
"Failed to get number of cores");
|
||||
_numberOfCores = 1;
|
||||
}
|
||||
#else
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceUtility, -1,
|
||||
"No function to get number of cores");
|
||||
_numberOfCores = 1;
|
||||
#endif
|
||||
}
|
||||
return _numberOfCores;
|
||||
}
|
||||
|
||||
CpuWrapper* CpuWrapper::CreateCpu()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return new CpuWindows();
|
||||
#elif (defined(WEBRTC_MAC) || defined(WEBRTC_MAC_INTEL))
|
||||
return new CpuWrapperMac();
|
||||
#elif defined(ANDROID)
|
||||
return 0;
|
||||
#else
|
||||
return new CpuLinux();
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
60
system_wrappers/source/cpu_features.cc
Normal file
60
system_wrappers/source/cpu_features.cc
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "cpu_features_wrapper.h"
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
// Actual feature detection for x86.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
int cpu_info[4];
|
||||
cpuid(cpu_info, 1);
|
||||
if (feature == kSSE2) {
|
||||
return 0 != (cpu_info[3] & 0x04000000);
|
||||
}
|
||||
if (feature == kSSE3) {
|
||||
return 0 != (cpu_info[2] & 0x00000001);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Default to straight C for other platforms.
|
||||
static int GetCPUInfo(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfo = GetCPUInfo;
|
||||
WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM = GetCPUInfoNoASM;
|
168
system_wrappers/source/cpu_linux.cc
Normal file
168
system_wrappers/source/cpu_linux.cc
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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 "cpu_linux.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace webrtc {
|
||||
CpuLinux::CpuLinux()
|
||||
{
|
||||
m_oldBusyTime = 0;
|
||||
m_oldIdleTime = 0;
|
||||
m_numCores = 0;
|
||||
m_numCores = GetNumCores();
|
||||
m_oldBusyTimeMulti = new long long[m_numCores];
|
||||
m_oldIdleTimeMulti = new long long[m_numCores];
|
||||
m_idleArray = new long long[m_numCores];
|
||||
m_busyArray = new long long[m_numCores];
|
||||
m_resultArray = new WebRtc_UWord32[m_numCores];
|
||||
|
||||
GetData(m_oldBusyTime, m_oldIdleTime, m_busyArray, m_idleArray);
|
||||
}
|
||||
|
||||
CpuLinux::~CpuLinux()
|
||||
{
|
||||
delete [] m_oldBusyTimeMulti;
|
||||
delete [] m_oldIdleTimeMulti;
|
||||
delete [] m_idleArray;
|
||||
delete [] m_busyArray;
|
||||
delete [] m_resultArray;
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuLinux::CpuUsage()
|
||||
{
|
||||
WebRtc_UWord32 dummy = 0;
|
||||
WebRtc_UWord32* dummyArray = NULL;
|
||||
return CpuUsageMultiCore(dummy, dummyArray);
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuLinux::CpuUsageMultiCore(WebRtc_UWord32& numCores,
|
||||
WebRtc_UWord32*& coreArray)
|
||||
{
|
||||
coreArray = m_resultArray;
|
||||
numCores = m_numCores;
|
||||
long long busy = 0;
|
||||
long long idle = 0;
|
||||
GetData(busy, idle, m_busyArray, m_idleArray);
|
||||
|
||||
long long deltaBusy = busy - m_oldBusyTime;
|
||||
long long deltaIdle = idle - m_oldIdleTime;
|
||||
m_oldBusyTime = busy;
|
||||
m_oldIdleTime = idle;
|
||||
|
||||
int retVal = -1;
|
||||
if (deltaBusy + deltaIdle == 0)
|
||||
{
|
||||
retVal = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = (int)(100 * (deltaBusy) / (deltaBusy + deltaIdle));
|
||||
}
|
||||
|
||||
if (coreArray == NULL)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i < m_numCores; i++)
|
||||
{
|
||||
deltaBusy = m_busyArray[i] - m_oldBusyTimeMulti[i];
|
||||
deltaIdle = m_idleArray[i] - m_oldIdleTimeMulti[i];
|
||||
m_oldBusyTimeMulti[i] = m_busyArray[i];
|
||||
m_oldIdleTimeMulti[i] = m_idleArray[i];
|
||||
if(deltaBusy + deltaIdle == 0)
|
||||
{
|
||||
coreArray[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
coreArray[i] = (int)(100 * (deltaBusy) / (deltaBusy+deltaIdle));
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
int CpuLinux::GetData(long long& busy, long long& idle, long long*& busyArray,
|
||||
long long*& idleArray)
|
||||
{
|
||||
FILE* fp = fopen("/proc/stat", "r");
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char line[100];
|
||||
char* dummy = fgets(line, 100, fp);
|
||||
char firstWord[100];
|
||||
sscanf(line, "%s ", firstWord);
|
||||
if(strncmp(firstWord, "cpu", 3)!=0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
char sUser[100];
|
||||
char sNice[100];
|
||||
char sSystem[100];
|
||||
char sIdle[100];
|
||||
sscanf(line, "%s %s %s %s %s ", firstWord, sUser, sNice, sSystem, sIdle);
|
||||
long long luser = atoll(sUser);
|
||||
long long lnice = atoll(sNice);
|
||||
long long lsystem = atoll(sSystem);
|
||||
long long lidle = atoll (sIdle);
|
||||
|
||||
busy = luser + lnice + lsystem;
|
||||
idle = lidle;
|
||||
for (WebRtc_UWord32 i = 0; i < m_numCores; i++)
|
||||
{
|
||||
dummy = fgets(line, 100, fp);
|
||||
sscanf(line, "%s %s %s %s %s ", firstWord, sUser, sNice, sSystem,
|
||||
sIdle);
|
||||
luser = atoll(sUser);
|
||||
lnice = atoll(sNice);
|
||||
lsystem = atoll(sSystem);
|
||||
lidle = atoll (sIdle);
|
||||
busyArray[i] = luser + lnice + lsystem;
|
||||
idleArray[i] = lidle;
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CpuLinux::GetNumCores()
|
||||
{
|
||||
FILE* fp = fopen("/proc/stat", "r");
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Skip first line
|
||||
char line[100];
|
||||
char* dummy = fgets(line, 100, fp);
|
||||
int numCores = -1;
|
||||
char firstWord[100];
|
||||
do
|
||||
{
|
||||
numCores++;
|
||||
if (fgets(line, 100, fp))
|
||||
{
|
||||
sscanf(line, "%s ", firstWord);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (strncmp(firstWord, "cpu", 3) == 0);
|
||||
fclose(fp);
|
||||
return numCores;
|
||||
}
|
||||
} // namespace webrtc
|
51
system_wrappers/source/cpu_linux.h
Normal file
51
system_wrappers/source/cpu_linux.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
||||
|
||||
#include "cpu_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CpuLinux : public CpuWrapper
|
||||
{
|
||||
public:
|
||||
CpuLinux();
|
||||
virtual ~CpuLinux();
|
||||
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* /*pProcessName*/,
|
||||
WebRtc_UWord32 /*length*/) {return 0;}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 /*dwProcessID*/) {return 0;}
|
||||
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& numCores,
|
||||
WebRtc_UWord32*& array);
|
||||
|
||||
virtual void Reset() {return;}
|
||||
virtual void Stop() {return;}
|
||||
private:
|
||||
int GetData(long long& busy, long long& idle, long long*& busyArray,
|
||||
long long*& idleArray);
|
||||
int GetNumCores();
|
||||
|
||||
long long m_oldBusyTime;
|
||||
long long m_oldIdleTime;
|
||||
|
||||
long long* m_oldBusyTimeMulti;
|
||||
long long* m_oldIdleTimeMulti;
|
||||
|
||||
long long* m_idleArray;
|
||||
long long* m_busyArray;
|
||||
WebRtc_UWord32* m_resultArray;
|
||||
WebRtc_UWord32 m_numCores;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
132
system_wrappers/source/cpu_mac.cc
Normal file
132
system_wrappers/source/cpu_mac.cc
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 "cpu_mac.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_error.h>
|
||||
|
||||
#include "tick_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
CpuWrapperMac::CpuWrapperMac() : _cpuUsage(NULL)
|
||||
{
|
||||
natural_t cpuCount;
|
||||
processor_info_array_t infoArray;
|
||||
mach_msg_type_number_t infoCount;
|
||||
|
||||
kern_return_t error = host_processor_info(mach_host_self(),
|
||||
PROCESSOR_CPU_LOAD_INFO,
|
||||
&cpuCount,
|
||||
&infoArray,
|
||||
&infoCount);
|
||||
if (error)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_cpuUsage = new WebRtc_UWord32[cpuCount];
|
||||
_lastTickCount = new WebRtc_Word64[cpuCount];
|
||||
_lastTime = TickTime::MillisecondTimestamp();
|
||||
|
||||
processor_cpu_load_info_data_t* cpuLoadInfo =
|
||||
(processor_cpu_load_info_data_t*) infoArray;
|
||||
for (unsigned int cpu= 0; cpu < cpuCount; cpu++)
|
||||
{
|
||||
WebRtc_Word64 ticks = 0;
|
||||
for (int state = 0; state < 2; state++)
|
||||
{
|
||||
ticks += cpuLoadInfo[cpu].cpu_ticks[state];
|
||||
}
|
||||
_lastTickCount[cpu] = ticks;
|
||||
}
|
||||
vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);
|
||||
}
|
||||
|
||||
CpuWrapperMac::~CpuWrapperMac()
|
||||
{
|
||||
delete _cpuUsage;
|
||||
delete _lastTickCount;
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuWrapperMac::CpuUsage()
|
||||
{
|
||||
WebRtc_UWord32 numCores;
|
||||
WebRtc_UWord32* array = NULL;
|
||||
return CpuUsageMultiCore(numCores, array);
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& numCores,
|
||||
WebRtc_UWord32*& array)
|
||||
{
|
||||
natural_t cpuCount;
|
||||
processor_info_array_t infoArray;
|
||||
mach_msg_type_number_t infoCount;
|
||||
|
||||
// sanity check
|
||||
if(_cpuUsage == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
WebRtc_Word64 now = TickTime::MillisecondTimestamp();
|
||||
WebRtc_Word64 timeDiffMS = now - _lastTime;
|
||||
// TODO(hellner) why block here? Why not just return the old
|
||||
// value? Is this behavior consistent across all
|
||||
// platforms?
|
||||
// Make sure that at least 500 ms pass between calls.
|
||||
if(timeDiffMS < 500)
|
||||
{
|
||||
usleep((500-timeDiffMS)*1000);
|
||||
return CpuUsageMultiCore(numCores, array);
|
||||
}
|
||||
_lastTime = now;
|
||||
|
||||
kern_return_t error = host_processor_info(mach_host_self(),
|
||||
PROCESSOR_CPU_LOAD_INFO,
|
||||
&cpuCount,
|
||||
&infoArray,
|
||||
&infoCount);
|
||||
if (error)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
processor_cpu_load_info_data_t* cpuLoadInfo =
|
||||
(processor_cpu_load_info_data_t*) infoArray;
|
||||
|
||||
WebRtc_Word32 totalCpuUsage = 0;
|
||||
for (unsigned int cpu = 0; cpu < cpuCount; cpu++)
|
||||
{
|
||||
WebRtc_Word64 ticks = 0;
|
||||
for (int state = 0; state < 2; state++)
|
||||
{
|
||||
ticks += cpuLoadInfo[cpu].cpu_ticks[state];
|
||||
}
|
||||
if(timeDiffMS <= 0)
|
||||
{
|
||||
_cpuUsage[cpu] = 0;
|
||||
}else {
|
||||
_cpuUsage[cpu] = (WebRtc_UWord32)((1000 *
|
||||
(ticks - _lastTickCount[cpu])) /
|
||||
timeDiffMS);
|
||||
}
|
||||
_lastTickCount[cpu] = ticks;
|
||||
totalCpuUsage += _cpuUsage[cpu];
|
||||
}
|
||||
|
||||
vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);
|
||||
|
||||
numCores = cpuCount;
|
||||
array = _cpuUsage;
|
||||
return totalCpuUsage/cpuCount;
|
||||
}
|
||||
} // namespace webrtc
|
44
system_wrappers/source/cpu_mac.h
Normal file
44
system_wrappers/source/cpu_mac.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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_CPU_MAC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_MAC_H_
|
||||
|
||||
#include "cpu_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CpuWrapperMac : public CpuWrapper
|
||||
{
|
||||
public:
|
||||
CpuWrapperMac();
|
||||
virtual ~CpuWrapperMac();
|
||||
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* /*pProcessName*/,
|
||||
WebRtc_UWord32 /*length*/) {return -1;}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 /*dwProcessID*/) {return -1;}
|
||||
|
||||
// Note: this class will block the call and sleep if called too fast
|
||||
// This function blocks the calling thread if the thread is calling it more
|
||||
// often than every 500 ms.
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& numCores,
|
||||
WebRtc_UWord32*& array);
|
||||
|
||||
virtual void Reset() {}
|
||||
virtual void Stop() {}
|
||||
|
||||
private:
|
||||
WebRtc_UWord32* _cpuUsage;
|
||||
WebRtc_Word64* _lastTickCount;
|
||||
WebRtc_Word64 _lastTime;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_MAC_H_
|
501
system_wrappers/source/cpu_windows.cc
Normal file
501
system_wrappers/source/cpu_windows.cc
Normal file
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* 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 "cpu_windows.h"
|
||||
|
||||
#define _WIN32_DCOM
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "event_wrapper.h"
|
||||
#include "thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
WebRtc_Word32 CpuWindows::CpuUsage()
|
||||
{
|
||||
if (!initialized_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Last element is the average
|
||||
return cpu_usage_[number_of_objects_ - 1];
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuWindows::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& cpu_usage)
|
||||
{
|
||||
if (!initialized_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
num_cores = number_of_objects_ - 1;
|
||||
cpu_usage = cpu_usage_;
|
||||
return cpu_usage_[number_of_objects_-1];
|
||||
}
|
||||
|
||||
CpuWindows::CpuWindows()
|
||||
: cpu_polling_thread(NULL),
|
||||
initialize_(true),
|
||||
initialized_(false),
|
||||
terminate_(false),
|
||||
cpu_usage_(NULL),
|
||||
wbem_enum_access_(NULL),
|
||||
number_of_objects_(0),
|
||||
cpu_usage_handle_(0),
|
||||
previous_processor_timestamp_(NULL),
|
||||
timestamp_sys_100_ns_handle_(0),
|
||||
previous_100ns_timestamp_(NULL),
|
||||
wbem_service_(NULL),
|
||||
wbem_refresher_(NULL),
|
||||
wbem_enum_(NULL)
|
||||
{
|
||||
// All resources are allocated in PollingCpu().
|
||||
if (AllocateComplexDataTypes())
|
||||
{
|
||||
const bool success = StartPollingCpu();
|
||||
assert(success);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
CpuWindows::~CpuWindows()
|
||||
{
|
||||
// All resources are reclaimed in StopPollingCpu().
|
||||
const bool success = StopPollingCpu();
|
||||
assert(success);
|
||||
DeAllocateComplexDataTypes();
|
||||
}
|
||||
|
||||
bool CpuWindows::AllocateComplexDataTypes()
|
||||
{
|
||||
cpu_polling_thread = ThreadWrapper::CreateThread(
|
||||
CpuWindows::Process,
|
||||
reinterpret_cast<void*>(this),
|
||||
kNormalPriority,
|
||||
"CpuWindows");
|
||||
init_crit_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
init_cond_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
terminate_crit_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
terminate_cond_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
sleep_event = EventWrapper::Create();
|
||||
return (cpu_polling_thread != NULL) && (init_crit_ != NULL) &&
|
||||
(init_cond_ != NULL) && (terminate_crit_ != NULL) &&
|
||||
(terminate_cond_ != NULL) && (sleep_event != NULL);
|
||||
}
|
||||
|
||||
void CpuWindows::DeAllocateComplexDataTypes()
|
||||
{
|
||||
if (sleep_event != NULL)
|
||||
{
|
||||
delete sleep_event;
|
||||
sleep_event = NULL;
|
||||
}
|
||||
if (terminate_cond_ != NULL)
|
||||
{
|
||||
delete terminate_cond_;
|
||||
terminate_cond_ = NULL;
|
||||
}
|
||||
if (terminate_crit_ != NULL)
|
||||
{
|
||||
delete terminate_crit_;
|
||||
terminate_crit_ = NULL;
|
||||
}
|
||||
if (init_cond_ != NULL)
|
||||
{
|
||||
delete init_cond_;
|
||||
init_cond_ = NULL;
|
||||
}
|
||||
if (init_crit_ != NULL)
|
||||
{
|
||||
delete init_crit_;
|
||||
init_crit_ = NULL;
|
||||
}
|
||||
if (cpu_polling_thread != NULL)
|
||||
{
|
||||
delete cpu_polling_thread;
|
||||
cpu_polling_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CpuWindows::StartPollingCpu()
|
||||
{
|
||||
unsigned int dummy_id = 0;
|
||||
if (!cpu_polling_thread->Start(dummy_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
{
|
||||
CriticalSectionScoped cs(*init_crit_);
|
||||
while(initialize_)
|
||||
{
|
||||
init_cond_->SleepCS(*init_crit_);
|
||||
}
|
||||
}
|
||||
if (!initialized_)
|
||||
{
|
||||
cpu_polling_thread->Stop();
|
||||
return false;
|
||||
}
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
bool CpuWindows::StopPollingCpu()
|
||||
{
|
||||
if (!initialized_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CriticalSectionScoped cs(*terminate_crit_);
|
||||
terminate_ = true;
|
||||
sleep_event->Set();
|
||||
while (!terminated_)
|
||||
{
|
||||
terminate_cond_->SleepCS(*terminate_crit_);
|
||||
}
|
||||
cpu_polling_thread->Stop();
|
||||
delete cpu_polling_thread;
|
||||
cpu_polling_thread = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::Process(void* thread_object)
|
||||
{
|
||||
return reinterpret_cast<CpuWindows*>(thread_object)->ProcessImpl();
|
||||
}
|
||||
|
||||
bool CpuWindows::ProcessImpl()
|
||||
{
|
||||
{
|
||||
CriticalSectionScoped cs(*terminate_crit_);
|
||||
if (terminate_)
|
||||
{
|
||||
const bool success = Terminate();
|
||||
assert(success);
|
||||
terminated_ = true;
|
||||
terminate_cond_->WakeAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Initialize on first iteration
|
||||
if (initialize_)
|
||||
{
|
||||
CriticalSectionScoped cs(*init_crit_);
|
||||
initialize_ = false;
|
||||
const bool success = Initialize();
|
||||
init_cond_->WakeAll();
|
||||
if (!success || !initialized_)
|
||||
{
|
||||
initialized_ = false;
|
||||
terminate_ = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Approximately one seconds sleep for each CPU measurement. Precision is
|
||||
// not important. 1 second refresh rate is also used by Performance Monitor
|
||||
// (perfmon).
|
||||
if(kEventTimeout != sleep_event->Wait(1000))
|
||||
{
|
||||
// Terminating. No need to update CPU usage.
|
||||
assert(terminate_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// UpdateCpuUsage() returns false if a single (or more) CPU read(s) failed.
|
||||
// Not a major problem if it happens but make sure it doesnt trigger in
|
||||
// debug.
|
||||
const bool success = UpdateCpuUsage();
|
||||
assert(success);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::CreateWmiConnection()
|
||||
{
|
||||
IWbemLocator* service_locator = NULL;
|
||||
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IWbemLocator,
|
||||
reinterpret_cast<void**> (&service_locator));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// To get the WMI service specify the WMI namespace.
|
||||
BSTR wmi_namespace = SysAllocString(L"\\\\.\\root\\cimv2");
|
||||
if (wmi_namespace == NULL)
|
||||
{
|
||||
// This type of failure signifies running out of memory.
|
||||
service_locator->Release();
|
||||
return false;
|
||||
}
|
||||
hr = service_locator->ConnectServer(wmi_namespace, NULL, NULL, NULL, 0L,
|
||||
NULL, NULL, &wbem_service_);
|
||||
SysFreeString(wmi_namespace);
|
||||
service_locator->Release();
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
// Sets up WMI refresher and enum
|
||||
bool CpuWindows::CreatePerfOsRefresher()
|
||||
{
|
||||
// Create refresher.
|
||||
HRESULT hr = CoCreateInstance(CLSID_WbemRefresher, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IWbemRefresher,
|
||||
reinterpret_cast<void**> (&wbem_refresher_));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Create PerfOS_Processor enum.
|
||||
IWbemConfigureRefresher* wbem_refresher_config = NULL;
|
||||
hr = wbem_refresher_->QueryInterface(
|
||||
IID_IWbemConfigureRefresher,
|
||||
reinterpret_cast<void**> (&wbem_refresher_config));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Don't care about the particular id for the enum.
|
||||
long enum_id = 0;
|
||||
hr = wbem_refresher_config->AddEnum(wbem_service_,
|
||||
L"Win32_PerfRawData_PerfOS_Processor",
|
||||
0, NULL, &wbem_enum_, &enum_id);
|
||||
wbem_refresher_config->Release();
|
||||
wbem_refresher_config = NULL;
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
// Have to pull the first round of data to be able set the handles.
|
||||
bool CpuWindows::CreatePerfOsCpuHandles()
|
||||
{
|
||||
// Update the refresher so that there is data available in wbem_enum_.
|
||||
wbem_refresher_->Refresh(0L);
|
||||
|
||||
// The number of enumerators is the number of processor + 1 (the total).
|
||||
// This is unknown at this point.
|
||||
DWORD number_returned = 0;
|
||||
HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
|
||||
wbem_enum_access_, &number_returned);
|
||||
// number_returned indicates the number of enumerators that are needed.
|
||||
if (hr == WBEM_E_BUFFER_TOO_SMALL &&
|
||||
number_returned > number_of_objects_)
|
||||
{
|
||||
// Allocate the number IWbemObjectAccess asked for by the
|
||||
// GetObjects(..) function.
|
||||
wbem_enum_access_ = new IWbemObjectAccess*[number_returned];
|
||||
cpu_usage_ = new WebRtc_UWord32[number_returned];
|
||||
previous_processor_timestamp_ = new unsigned __int64[number_returned];
|
||||
previous_100ns_timestamp_ = new unsigned __int64[number_returned];
|
||||
if ((wbem_enum_access_ == NULL) || (cpu_usage_ == NULL) ||
|
||||
(previous_processor_timestamp_ == NULL) ||
|
||||
(previous_100ns_timestamp_ == NULL))
|
||||
{
|
||||
// Out of memory.
|
||||
return false;
|
||||
}
|
||||
|
||||
SecureZeroMemory(wbem_enum_access_, number_returned *
|
||||
sizeof(IWbemObjectAccess*));
|
||||
memset(cpu_usage_, 0, sizeof(int) * number_returned);
|
||||
memset(previous_processor_timestamp_, 0, sizeof(unsigned __int64) *
|
||||
number_returned);
|
||||
memset(previous_100ns_timestamp_, 0, sizeof(unsigned __int64) *
|
||||
number_returned);
|
||||
|
||||
number_of_objects_ = number_returned;
|
||||
// Read should be successfull now that memory has been allocated.
|
||||
hr = wbem_enum_->GetObjects(0L, number_of_objects_, wbem_enum_access_,
|
||||
&number_returned);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 enumerators should not be enough. Something has gone wrong here.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the enumerator handles that are needed for calculating CPU usage.
|
||||
CIMTYPE cpu_usage_type;
|
||||
hr = wbem_enum_access_[0]->GetPropertyHandle(L"PercentProcessorTime",
|
||||
&cpu_usage_type,
|
||||
&cpu_usage_handle_);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CIMTYPE timestamp_sys_100_ns_type;
|
||||
hr = wbem_enum_access_[0]->GetPropertyHandle(L"TimeStamp_Sys100NS",
|
||||
×tamp_sys_100_ns_type,
|
||||
×tamp_sys_100_ns_handle_);
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
bool CpuWindows::Initialize()
|
||||
{
|
||||
if (terminate_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Initialize COM library.
|
||||
HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateWmiConnection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CreatePerfOsRefresher())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CreatePerfOsCpuHandles())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::Terminate()
|
||||
{
|
||||
// Reverse order of Initialize().
|
||||
// Some compilers complain about deleting NULL though it's well defined
|
||||
if (previous_100ns_timestamp_ != NULL)
|
||||
{
|
||||
delete[] previous_100ns_timestamp_;
|
||||
previous_100ns_timestamp_ = NULL;
|
||||
}
|
||||
if (previous_processor_timestamp_ != NULL)
|
||||
{
|
||||
delete[] previous_processor_timestamp_;
|
||||
previous_processor_timestamp_ = NULL;
|
||||
}
|
||||
if (cpu_usage_ != NULL)
|
||||
{
|
||||
delete[] cpu_usage_;
|
||||
cpu_usage_ = NULL;
|
||||
}
|
||||
if (wbem_enum_access_ != NULL)
|
||||
{
|
||||
for (DWORD i = 0; i < number_of_objects_; i++)
|
||||
{
|
||||
if(wbem_enum_access_[i] != NULL)
|
||||
{
|
||||
wbem_enum_access_[i]->Release();
|
||||
}
|
||||
}
|
||||
delete[] wbem_enum_access_;
|
||||
wbem_enum_access_ = NULL;
|
||||
}
|
||||
if (wbem_enum_ != NULL)
|
||||
{
|
||||
wbem_enum_->Release();
|
||||
wbem_enum_ = NULL;
|
||||
}
|
||||
if (wbem_refresher_ != NULL)
|
||||
{
|
||||
wbem_refresher_->Release();
|
||||
wbem_refresher_ = NULL;
|
||||
}
|
||||
if (wbem_service_ != NULL)
|
||||
{
|
||||
wbem_service_->Release();
|
||||
wbem_service_ = NULL;
|
||||
}
|
||||
// CoUninitialized should be called once for every CoInitializeEx.
|
||||
// Regardless if it failed or not.
|
||||
CoUninitialize();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CpuWindows::UpdateCpuUsage()
|
||||
{
|
||||
wbem_refresher_->Refresh(0L);
|
||||
DWORD number_returned = 0;
|
||||
HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
|
||||
wbem_enum_access_,&number_returned);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wbem_enum_access_ has already been allocated. Unless the number of
|
||||
// CPUs change runtime this should not happen.
|
||||
return false;
|
||||
}
|
||||
unsigned __int64 cpu_usage = 0;
|
||||
unsigned __int64 timestamp_100ns = 0;
|
||||
bool returnValue = true;
|
||||
for (DWORD i = 0; i < number_returned; i++)
|
||||
{
|
||||
hr = wbem_enum_access_[i]->ReadQWORD(cpu_usage_handle_,&cpu_usage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
hr = wbem_enum_access_[i]->ReadQWORD(timestamp_sys_100_ns_handle_,
|
||||
×tamp_100ns);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
wbem_enum_access_[i]->Release();
|
||||
wbem_enum_access_[i] = NULL;
|
||||
|
||||
const bool wrapparound =
|
||||
(previous_processor_timestamp_[i] > cpu_usage) ||
|
||||
(previous_100ns_timestamp_[i] > timestamp_100ns);
|
||||
const bool first_time = (previous_processor_timestamp_[i] == 0) ||
|
||||
(previous_100ns_timestamp_[i] == 0);
|
||||
if (wrapparound || first_time)
|
||||
{
|
||||
previous_processor_timestamp_[i] = cpu_usage;
|
||||
previous_100ns_timestamp_[i] = timestamp_100ns;
|
||||
continue;
|
||||
}
|
||||
const unsigned __int64 processor_timestamp_delta =
|
||||
cpu_usage - previous_processor_timestamp_[i];
|
||||
const unsigned __int64 timestamp_100ns_delta =
|
||||
timestamp_100ns - previous_100ns_timestamp_[i];
|
||||
|
||||
if (processor_timestamp_delta >= timestamp_100ns_delta)
|
||||
{
|
||||
cpu_usage_[i] = 0;
|
||||
} else {
|
||||
// Quotient must be float since the division is guaranteed to yield
|
||||
// a value between 0 and 1 which is 0 in integer division.
|
||||
const float delta_quotient =
|
||||
static_cast<float>(processor_timestamp_delta) /
|
||||
static_cast<float>(timestamp_100ns_delta);
|
||||
cpu_usage_[i] = 100 - static_cast<WebRtc_UWord32>(delta_quotient *
|
||||
100);
|
||||
}
|
||||
previous_processor_timestamp_[i] = cpu_usage;
|
||||
previous_100ns_timestamp_[i] = timestamp_100ns;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
} // namespace webrtc
|
102
system_wrappers/source/cpu_windows.h
Normal file
102
system_wrappers/source/cpu_windows.h
Normal file
@ -0,0 +1,102 @@
|
||||
// This file contains a Windows implementation of CpuWrapper.
|
||||
// Note: Windows XP, Windows Server 2003 are the minimum requirements.
|
||||
// The requirements are due to the implementation being based on
|
||||
// WMI.
|
||||
/*
|
||||
* 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_CPU_WINDOWS_NO_CPOL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
|
||||
|
||||
#include "cpu_wrapper.h"
|
||||
|
||||
#include <Wbemidl.h>
|
||||
|
||||
namespace webrtc {
|
||||
class ConditionVariableWrapper;
|
||||
class CriticalSectionWrapper;
|
||||
class EventWrapper;
|
||||
class ThreadWrapper;
|
||||
|
||||
class CpuWindows : public CpuWrapper
|
||||
{
|
||||
public:
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* /*pProcessName*/,
|
||||
WebRtc_UWord32 /*length*/) {return -1;}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 /*dwProcessID*/) {return -1;}
|
||||
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& cpu_usage);
|
||||
|
||||
virtual void Reset() {}
|
||||
virtual void Stop() {}
|
||||
|
||||
CpuWindows();
|
||||
virtual ~CpuWindows();
|
||||
private:
|
||||
bool AllocateComplexDataTypes();
|
||||
void DeAllocateComplexDataTypes();
|
||||
|
||||
bool StartPollingCpu();
|
||||
bool StopPollingCpu();
|
||||
|
||||
static bool Process(void* thread_object);
|
||||
bool ProcessImpl();
|
||||
|
||||
bool CreateWmiConnection();
|
||||
bool CreatePerfOsRefresher();
|
||||
bool CreatePerfOsCpuHandles();
|
||||
bool Initialize();
|
||||
bool Terminate();
|
||||
|
||||
bool UpdateCpuUsage();
|
||||
|
||||
ThreadWrapper* cpu_polling_thread;
|
||||
|
||||
bool initialize_;
|
||||
bool initialized_;
|
||||
CriticalSectionWrapper* init_crit_;
|
||||
ConditionVariableWrapper* init_cond_;
|
||||
|
||||
bool terminate_;
|
||||
bool terminated_;
|
||||
CriticalSectionWrapper* terminate_crit_;
|
||||
ConditionVariableWrapper* terminate_cond_;
|
||||
|
||||
// For sleep with wake-up functionality.
|
||||
EventWrapper* sleep_event;
|
||||
|
||||
// Will be an array. Just care about CPU 0 for now.
|
||||
WebRtc_UWord32* cpu_usage_;
|
||||
|
||||
// One IWbemObjectAccess for each processor and one for the total.
|
||||
// 0-n-1 is the individual processors.
|
||||
// n is the total.
|
||||
IWbemObjectAccess** wbem_enum_access_;
|
||||
DWORD number_of_objects_;
|
||||
|
||||
// Cpu timestamp
|
||||
long cpu_usage_handle_;
|
||||
unsigned __int64* previous_processor_timestamp_;
|
||||
|
||||
// Timestamp
|
||||
long timestamp_sys_100_ns_handle_;
|
||||
unsigned __int64* previous_100ns_timestamp_;
|
||||
|
||||
IWbemServices* wbem_service_;
|
||||
|
||||
IWbemRefresher* wbem_refresher_;
|
||||
|
||||
IWbemHiPerfEnum* wbem_enum_;
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
|
27
system_wrappers/source/critical_section.cc
Normal file
27
system_wrappers/source/critical_section.cc
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 "critical_section_windows.h"
|
||||
#else
|
||||
#include "critical_section_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
CriticalSectionWrapper* CriticalSectionWrapper::CreateCriticalSection()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return new CriticalSectionWindows();
|
||||
#else
|
||||
return new CriticalSectionLinux();
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
38
system_wrappers/source/critical_section_linux.cc
Normal file
38
system_wrappers/source/critical_section_linux.cc
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 "critical_section_linux.h"
|
||||
|
||||
namespace webrtc {
|
||||
CriticalSectionLinux::CriticalSectionLinux()
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&_mutex, &attr);
|
||||
}
|
||||
|
||||
CriticalSectionLinux::~CriticalSectionLinux()
|
||||
{
|
||||
pthread_mutex_destroy(&_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionLinux::Enter()
|
||||
{
|
||||
pthread_mutex_lock(&_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionLinux::Leave()
|
||||
{
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
}
|
||||
} // namespace webrtc
|
35
system_wrappers/source/critical_section_linux.h
Normal file
35
system_wrappers/source/critical_section_linux.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_LINUX_H_
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionLinux : public CriticalSectionWrapper
|
||||
{
|
||||
public:
|
||||
CriticalSectionLinux();
|
||||
|
||||
virtual ~CriticalSectionLinux();
|
||||
|
||||
virtual void Enter();
|
||||
virtual void Leave();
|
||||
|
||||
private:
|
||||
pthread_mutex_t _mutex;
|
||||
friend class ConditionVariableLinux;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_LINUX_H_
|
35
system_wrappers/source/critical_section_windows.cc
Normal file
35
system_wrappers/source/critical_section_windows.cc
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "critical_section_windows.h"
|
||||
|
||||
namespace webrtc {
|
||||
CriticalSectionWindows::CriticalSectionWindows()
|
||||
{
|
||||
InitializeCriticalSection(&crit);
|
||||
}
|
||||
|
||||
CriticalSectionWindows::~CriticalSectionWindows()
|
||||
{
|
||||
DeleteCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Enter()
|
||||
{
|
||||
EnterCriticalSection(&crit);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalSectionWindows::Leave()
|
||||
{
|
||||
LeaveCriticalSection(&crit);
|
||||
}
|
||||
} // namespace webrtc
|
36
system_wrappers/source/critical_section_windows.h
Normal file
36
system_wrappers/source/critical_section_windows.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
#include <windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWindows : public CriticalSectionWrapper
|
||||
{
|
||||
public:
|
||||
CriticalSectionWindows();
|
||||
|
||||
virtual ~CriticalSectionWindows();
|
||||
|
||||
virtual void Enter();
|
||||
virtual void Leave();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION crit;
|
||||
|
||||
friend class ConditionVariableWindows;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
|
52
system_wrappers/source/event.cc
Normal file
52
system_wrappers/source/event.cc
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 "event_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "event_windows.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include "event_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
EventWrapper* EventWrapper::Create()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return new EventWindows();
|
||||
#else
|
||||
return EventLinux::Create();
|
||||
#endif
|
||||
}
|
||||
|
||||
int EventWrapper::KeyPressed()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
int keyDown = 0;
|
||||
for(int key = 0x20; key < 0x90; key++)
|
||||
{
|
||||
short res = GetAsyncKeyState(key);
|
||||
keyDown |= res%2; // Get the LSB
|
||||
}
|
||||
if(keyDown)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
324
system_wrappers/source/event_linux.cc
Normal file
324
system_wrappers/source/event_linux.cc
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* 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 "event_linux.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace webrtc {
|
||||
const long int E6 = 1000000;
|
||||
const long int E9 = 1000 * E6;
|
||||
|
||||
EventWrapper* EventLinux::Create()
|
||||
{
|
||||
EventLinux* ptr = new EventLinux;
|
||||
if (!ptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int error = ptr->Construct();
|
||||
if (error)
|
||||
{
|
||||
delete ptr;
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
EventLinux::EventLinux()
|
||||
: _timerThread(0),
|
||||
_timerEvent(0),
|
||||
_periodic(false),
|
||||
_time(0),
|
||||
_count(0),
|
||||
_state(kDown)
|
||||
{
|
||||
}
|
||||
|
||||
int EventLinux::Construct()
|
||||
{
|
||||
// Set start time to zero
|
||||
memset(&_tCreate, 0, sizeof(_tCreate));
|
||||
|
||||
int result = pthread_mutex_init(&mutex, 0);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
result = pthread_cond_init(&cond, 0);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
pthread_condattr_t condAttr;
|
||||
result = pthread_condattr_init(&condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_cond_init(&cond, &condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_condattr_destroy(&condAttr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
EventLinux::~EventLinux()
|
||||
{
|
||||
StopTimer();
|
||||
pthread_cond_destroy(&cond);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
bool EventLinux::Reset()
|
||||
{
|
||||
if (0 != pthread_mutex_lock(&mutex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_state = kDown;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventLinux::Set()
|
||||
{
|
||||
if (0 != pthread_mutex_lock(&mutex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_state = kUp;
|
||||
// Release all waiting threads
|
||||
pthread_cond_broadcast(&cond);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
EventTypeWrapper EventLinux::Wait(unsigned long timeout)
|
||||
{
|
||||
int retVal = 0;
|
||||
if (0 != pthread_mutex_lock(&mutex))
|
||||
{
|
||||
return kEventError;
|
||||
}
|
||||
|
||||
if (kDown == _state)
|
||||
{
|
||||
if (WEBRTC_EVENT_INFINITE != timeout)
|
||||
{
|
||||
timespec tEnd;
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &tEnd);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &tEnd);
|
||||
#endif
|
||||
#else
|
||||
timeval tVal;
|
||||
struct timezone tZone;
|
||||
tZone.tz_minuteswest = 0;
|
||||
tZone.tz_dsttime = 0;
|
||||
gettimeofday(&tVal,&tZone);
|
||||
TIMEVAL_TO_TIMESPEC(&tVal,&tEnd);
|
||||
#endif
|
||||
tEnd.tv_sec += timeout / 1000;
|
||||
tEnd.tv_nsec += (timeout - (timeout / 1000) * 1000) * E6;
|
||||
|
||||
if (tEnd.tv_nsec >= E9)
|
||||
{
|
||||
tEnd.tv_sec++;
|
||||
tEnd.tv_nsec -= E9;
|
||||
}
|
||||
retVal = pthread_cond_timedwait(&cond, &mutex, &tEnd);
|
||||
} else {
|
||||
retVal = pthread_cond_wait(&cond, &mutex);
|
||||
}
|
||||
}
|
||||
|
||||
_state = kDown;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
switch(retVal)
|
||||
{
|
||||
case 0:
|
||||
return kEventSignaled;
|
||||
case ETIMEDOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
EventTypeWrapper EventLinux::Wait(timespec& tPulse)
|
||||
{
|
||||
int retVal = 0;
|
||||
if (0 != pthread_mutex_lock(&mutex))
|
||||
{
|
||||
return kEventError;
|
||||
}
|
||||
|
||||
if (kUp != _state)
|
||||
{
|
||||
retVal = pthread_cond_timedwait(&cond, &mutex, &tPulse);
|
||||
}
|
||||
_state = kDown;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
switch(retVal)
|
||||
{
|
||||
case 0:
|
||||
return kEventSignaled;
|
||||
case ETIMEDOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventLinux::StartTimer(bool periodic, unsigned long time)
|
||||
{
|
||||
if (_timerThread)
|
||||
{
|
||||
if(_periodic)
|
||||
{
|
||||
// Timer already started.
|
||||
return false;
|
||||
} else {
|
||||
// New one shot timer
|
||||
_time = time;
|
||||
_tCreate.tv_sec = 0;
|
||||
_timerEvent->Set();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the timer thread
|
||||
_timerEvent = static_cast<EventLinux*>(EventWrapper::Create());
|
||||
const char* threadName = "WebRtc_event_timer_thread";
|
||||
_timerThread = ThreadWrapper::CreateThread(Run, this, kRealtimePriority,
|
||||
threadName);
|
||||
_periodic = periodic;
|
||||
_time = time;
|
||||
unsigned int id = 0;
|
||||
if (_timerThread->Start(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventLinux::Run(ThreadObj obj)
|
||||
{
|
||||
return static_cast<EventLinux*>(obj)->Process();
|
||||
}
|
||||
|
||||
bool EventLinux::Process()
|
||||
{
|
||||
if (_tCreate.tv_sec == 0)
|
||||
{
|
||||
#ifndef WEBRTC_MAC
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &_tCreate);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &_tCreate);
|
||||
#endif
|
||||
#else
|
||||
timeval tVal;
|
||||
struct timezone tZone;
|
||||
tZone.tz_minuteswest = 0;
|
||||
tZone.tz_dsttime = 0;
|
||||
gettimeofday(&tVal,&tZone);
|
||||
TIMEVAL_TO_TIMESPEC(&tVal,&_tCreate);
|
||||
#endif
|
||||
_count=0;
|
||||
}
|
||||
|
||||
timespec tEnd;
|
||||
unsigned long long time = _time * ++_count;
|
||||
tEnd.tv_sec = _tCreate.tv_sec + time/1000;
|
||||
tEnd.tv_nsec = _tCreate.tv_nsec + (time - (time/1000)*1000)*E6;
|
||||
|
||||
if ( tEnd.tv_nsec >= E9 )
|
||||
{
|
||||
tEnd.tv_sec++;
|
||||
tEnd.tv_nsec -= E9;
|
||||
}
|
||||
|
||||
switch(_timerEvent->Wait(tEnd))
|
||||
{
|
||||
case kEventSignaled:
|
||||
return true;
|
||||
case kEventError:
|
||||
return false;
|
||||
case kEventTimeout:
|
||||
break;
|
||||
}
|
||||
if(_periodic || _count==1)
|
||||
{
|
||||
Set();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventLinux::StopTimer()
|
||||
{
|
||||
if(_timerThread)
|
||||
{
|
||||
_timerThread->SetNotAlive();
|
||||
}
|
||||
if (_timerEvent)
|
||||
{
|
||||
_timerEvent->Set();
|
||||
}
|
||||
if (_timerThread)
|
||||
{
|
||||
if(!_timerThread->Stop())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
delete _timerThread;
|
||||
_timerThread = 0;
|
||||
}
|
||||
if (_timerEvent)
|
||||
{
|
||||
delete _timerEvent;
|
||||
_timerEvent = 0;
|
||||
}
|
||||
|
||||
// Set time to zero to force new reference time for the timer.
|
||||
memset(&_tCreate, 0, sizeof(_tCreate));
|
||||
_count=0;
|
||||
return true;
|
||||
}
|
||||
} // namespace webrtc
|
66
system_wrappers/source/event_linux.h
Normal file
66
system_wrappers/source/event_linux.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_LINUX_H_
|
||||
|
||||
#include "event_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
enum State
|
||||
{
|
||||
kUp = 1,
|
||||
kDown = 2
|
||||
};
|
||||
|
||||
class EventLinux : public EventWrapper
|
||||
{
|
||||
public:
|
||||
static EventWrapper* Create();
|
||||
|
||||
virtual ~EventLinux();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long maxTime);
|
||||
virtual bool Set();
|
||||
virtual bool Reset();
|
||||
|
||||
virtual bool StartTimer(bool periodic, unsigned long time);
|
||||
virtual bool StopTimer();
|
||||
|
||||
private:
|
||||
EventLinux();
|
||||
int Construct();
|
||||
|
||||
static bool Run(ThreadObj obj);
|
||||
bool Process();
|
||||
EventTypeWrapper Wait(timespec& tPulse);
|
||||
|
||||
|
||||
private:
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
ThreadWrapper* _timerThread;
|
||||
EventLinux* _timerEvent;
|
||||
timespec _tCreate;
|
||||
|
||||
bool _periodic;
|
||||
unsigned long _time; // In ms
|
||||
unsigned long _count;
|
||||
State _state;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_LINUX_H_
|
84
system_wrappers/source/event_windows.cc
Normal file
84
system_wrappers/source/event_windows.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 "event_windows.h"
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
namespace webrtc {
|
||||
EventWindows::EventWindows()
|
||||
: _event(::CreateEvent(NULL /* security attributes */,
|
||||
FALSE /* manual reset */,
|
||||
FALSE /* initial state */,
|
||||
NULL /* name of event */)),
|
||||
_timerID(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
EventWindows::~EventWindows()
|
||||
{
|
||||
CloseHandle(_event);
|
||||
}
|
||||
|
||||
bool EventWindows::Set()
|
||||
{
|
||||
// Note: setting an event that is already set has no effect.
|
||||
return SetEvent(_event);
|
||||
}
|
||||
|
||||
bool EventWindows::Reset()
|
||||
{
|
||||
return ResetEvent(_event);
|
||||
}
|
||||
|
||||
EventTypeWrapper EventWindows::Wait(unsigned long maxTime)
|
||||
{
|
||||
unsigned long res = WaitForSingleObject(_event, maxTime);
|
||||
switch(res)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
return kEventSignaled;
|
||||
case WAIT_TIMEOUT:
|
||||
return kEventTimeout;
|
||||
default:
|
||||
return kEventError;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventWindows::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);
|
||||
}
|
||||
|
||||
if (_timerID == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventWindows::StopTimer()
|
||||
{
|
||||
timeKillEvent(_timerID);
|
||||
_timerID = NULL;
|
||||
return true;
|
||||
}
|
||||
} // namespace webrtc
|
40
system_wrappers/source/event_windows.h
Normal file
40
system_wrappers/source/event_windows.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "event_wrapper.h"
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
class EventWindows : public EventWrapper
|
||||
{
|
||||
public:
|
||||
EventWindows();
|
||||
virtual ~EventWindows();
|
||||
|
||||
virtual EventTypeWrapper Wait(unsigned long maxTime);
|
||||
virtual bool Set();
|
||||
virtual bool Reset();
|
||||
|
||||
virtual bool StartTimer(bool periodic, unsigned long time);
|
||||
virtual bool StopTimer();
|
||||
|
||||
private:
|
||||
HANDLE _event;
|
||||
WebRtc_UWord32 _timerID;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
|
267
system_wrappers/source/file_impl.cc
Normal file
267
system_wrappers/source/file_impl.cc
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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 "file_impl.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
FileWrapper* FileWrapper::Create()
|
||||
{
|
||||
return new FileWrapperImpl();
|
||||
}
|
||||
|
||||
FileWrapperImpl::FileWrapperImpl()
|
||||
: _id(NULL),
|
||||
_open(false),
|
||||
_looping(false),
|
||||
_readOnly(false),
|
||||
_text(false),
|
||||
_maxSizeInBytes(-1),
|
||||
_sizeInBytes(0)
|
||||
{
|
||||
memset(_fileNameUTF8, 0, kMaxFileNameSize);
|
||||
}
|
||||
|
||||
FileWrapperImpl::~FileWrapperImpl()
|
||||
{
|
||||
if (_id != NULL)
|
||||
{
|
||||
fclose(_id);
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::CloseFile()
|
||||
{
|
||||
if (_id != NULL)
|
||||
{
|
||||
fclose(_id);
|
||||
_id = NULL;
|
||||
}
|
||||
memset(_fileNameUTF8, 0, kMaxFileNameSize);
|
||||
_open = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Rewind()
|
||||
{
|
||||
if(_looping || !_readOnly)
|
||||
{
|
||||
if (_id != NULL)
|
||||
{
|
||||
_sizeInBytes = 0;
|
||||
return fseek(_id, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::SetMaxFileSize(WebRtc_Word32 bytes)
|
||||
{
|
||||
_maxSizeInBytes = bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::Flush()
|
||||
{
|
||||
if (_id != NULL)
|
||||
{
|
||||
return fflush(_id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::FileName(WebRtc_Word8* fileNameUTF8,
|
||||
WebRtc_UWord32 size) const
|
||||
{
|
||||
WebRtc_Word32 len = static_cast<WebRtc_Word32>(strlen(_fileNameUTF8));
|
||||
if(len > kMaxFileNameSize)
|
||||
{
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
if(len < 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Make sure to NULL terminate
|
||||
if(size < (WebRtc_UWord32)len)
|
||||
{
|
||||
len = size - 1;
|
||||
}
|
||||
memcpy(fileNameUTF8, _fileNameUTF8, len);
|
||||
fileNameUTF8[len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
FileWrapperImpl::Open() const
|
||||
{
|
||||
return _open;
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::OpenFile(const WebRtc_Word8 *fileNameUTF8,
|
||||
const bool readOnly, const bool loop,
|
||||
const bool text)
|
||||
{
|
||||
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
|
||||
if (length > kMaxFileNameSize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_readOnly = readOnly;
|
||||
|
||||
FILE *tmpId = NULL;
|
||||
#if defined _WIN32
|
||||
wchar_t wideFileName[kMaxFileNameSize];
|
||||
wideFileName[0] = 0;
|
||||
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0 /*UTF8 flag*/,
|
||||
fileNameUTF8,
|
||||
-1 /*Null terminated string*/,
|
||||
wideFileName,
|
||||
kMaxFileNameSize);
|
||||
if(text)
|
||||
{
|
||||
if(readOnly)
|
||||
{
|
||||
tmpId = _wfopen(wideFileName, L"rt");
|
||||
} else {
|
||||
tmpId = _wfopen(wideFileName, L"wt");
|
||||
}
|
||||
} else {
|
||||
if(readOnly)
|
||||
{
|
||||
tmpId = _wfopen(wideFileName, L"rb");
|
||||
} else {
|
||||
tmpId = _wfopen(wideFileName, L"wb");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(text)
|
||||
{
|
||||
if(readOnly)
|
||||
{
|
||||
tmpId = fopen(fileNameUTF8, "rt");
|
||||
} else {
|
||||
tmpId = fopen(fileNameUTF8, "wt");
|
||||
}
|
||||
} else {
|
||||
if(readOnly)
|
||||
{
|
||||
tmpId = fopen(fileNameUTF8, "rb");
|
||||
} else {
|
||||
tmpId = fopen(fileNameUTF8, "wb");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmpId != NULL)
|
||||
{
|
||||
// + 1 comes fro copying the NULL termination charachter too
|
||||
memcpy(_fileNameUTF8, fileNameUTF8, length + 1);
|
||||
if (_id != NULL)
|
||||
{
|
||||
fclose(_id);
|
||||
}
|
||||
_id = tmpId;
|
||||
_looping = loop;
|
||||
_open = true;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FileWrapperImpl::Read(void *buf, int len)
|
||||
{
|
||||
if(len < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (_id != NULL)
|
||||
{
|
||||
WebRtc_Word32 res = static_cast<WebRtc_Word32>(fread(buf, 1, len, _id));
|
||||
if (res != len)
|
||||
{
|
||||
if(!_looping)
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 FileWrapperImpl::WriteText(const WebRtc_Word8* text, ...)
|
||||
{
|
||||
assert(!_readOnly);
|
||||
assert(!_text);
|
||||
|
||||
if (_id == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char tempBuff[kFileMaxTextMessageSize];
|
||||
if (text)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
#ifdef _WIN32
|
||||
_vsnprintf(tempBuff, kFileMaxTextMessageSize-1, text, args);
|
||||
#else
|
||||
vsnprintf(tempBuff, kFileMaxTextMessageSize-1, text, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
WebRtc_Word32 nBytes;
|
||||
nBytes = fprintf(_id, "%s", tempBuff);
|
||||
if (nBytes > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
CloseFile();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FileWrapperImpl::Write(const void* buf, int len)
|
||||
{
|
||||
assert(!_readOnly);
|
||||
if (_id != NULL)
|
||||
{
|
||||
// Check if it's time to stop writing.
|
||||
if ((_maxSizeInBytes != -1) &&
|
||||
_sizeInBytes + len > (WebRtc_UWord32)_maxSizeInBytes)
|
||||
{
|
||||
Flush();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t nBytes = fwrite((WebRtc_UWord8*)buf, 1, len, _id);
|
||||
if (nBytes > 0)
|
||||
{
|
||||
_sizeInBytes += static_cast<WebRtc_Word32>(nBytes);
|
||||
return true;
|
||||
}
|
||||
CloseFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace webrtc
|
57
system_wrappers/source/file_impl.h
Normal file
57
system_wrappers/source/file_impl.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 "file_wrapper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace webrtc {
|
||||
class FileWrapperImpl : public FileWrapper
|
||||
{
|
||||
public:
|
||||
FileWrapperImpl();
|
||||
virtual ~FileWrapperImpl();
|
||||
|
||||
virtual WebRtc_Word32 FileName(WebRtc_Word8* fileNameUTF8,
|
||||
WebRtc_UWord32 size) const;
|
||||
|
||||
virtual bool Open() const;
|
||||
|
||||
virtual WebRtc_Word32 OpenFile(const WebRtc_Word8* fileNameUTF8,
|
||||
const bool readOnly,
|
||||
const bool loop = false,
|
||||
const bool text = false);
|
||||
|
||||
virtual WebRtc_Word32 CloseFile();
|
||||
virtual WebRtc_Word32 SetMaxFileSize(WebRtc_Word32 bytes);
|
||||
virtual WebRtc_Word32 Flush();
|
||||
|
||||
virtual int Read(void* buf, int len);
|
||||
virtual bool Write(const void *buf, int len);
|
||||
virtual int Rewind();
|
||||
|
||||
virtual WebRtc_Word32 WriteText(const WebRtc_Word8* text, ...);
|
||||
|
||||
private:
|
||||
FILE* _id;
|
||||
bool _open;
|
||||
bool _looping;
|
||||
bool _readOnly;
|
||||
bool _text;
|
||||
WebRtc_Word32 _maxSizeInBytes; // -1 indicates file size limitation is off
|
||||
WebRtc_UWord32 _sizeInBytes;
|
||||
WebRtc_Word8 _fileNameUTF8[kMaxFileNameSize];
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_
|
289
system_wrappers/source/list_no_stl.cc
Normal file
289
system_wrappers/source/list_no_stl.cc
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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 "list_wrapper.h"
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
ListItem::ListItem(const void* item)
|
||||
: next_(0),
|
||||
prev_(0),
|
||||
item_ptr_(item),
|
||||
item_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ListItem::ListItem(const unsigned int item)
|
||||
: next_(0),
|
||||
prev_(0),
|
||||
item_ptr_(0),
|
||||
item_(item)
|
||||
{
|
||||
}
|
||||
|
||||
ListItem::~ListItem()
|
||||
{
|
||||
}
|
||||
|
||||
void* ListItem::GetItem() const
|
||||
{
|
||||
return const_cast<void*>(item_ptr_);
|
||||
}
|
||||
|
||||
unsigned int ListItem::GetUnsignedItem() const
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
|
||||
ListWrapper::ListWrapper()
|
||||
: critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
first_(0),
|
||||
last_(0),
|
||||
size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ListWrapper::~ListWrapper()
|
||||
{
|
||||
if (!Empty())
|
||||
{
|
||||
// TODO (hellner) I'm not sure this loggin is useful.
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
|
||||
"Potential memory leak in ListWrapper");
|
||||
// Remove all remaining list items.
|
||||
while (Erase(First()) == 0)
|
||||
{}
|
||||
}
|
||||
delete critical_section_;
|
||||
}
|
||||
|
||||
bool ListWrapper::Empty() const
|
||||
{
|
||||
return !first_ && !last_;
|
||||
}
|
||||
|
||||
unsigned int ListWrapper::GetSize() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
int ListWrapper::PushBack(const void* ptr)
|
||||
{
|
||||
ListItem* item = new ListItem(ptr);
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
PushBackImpl(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushBack(const unsigned int item_id)
|
||||
{
|
||||
ListItem* item = new ListItem(item_id);
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
PushBackImpl(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushFront(const unsigned int item_id)
|
||||
{
|
||||
ListItem* item = new ListItem(item_id);
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
PushFrontImpl(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushFront(const void* ptr)
|
||||
{
|
||||
ListItem* item = new ListItem(ptr);
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
PushFrontImpl(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PopFront()
|
||||
{
|
||||
return Erase(first_);
|
||||
}
|
||||
|
||||
int ListWrapper::PopBack()
|
||||
{
|
||||
return Erase(last_);
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::First() const
|
||||
{
|
||||
return first_;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Last() const
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Next(ListItem* item) const
|
||||
{
|
||||
if(!item)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return item->next_;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Previous(ListItem* item) const
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return item->prev_;
|
||||
}
|
||||
|
||||
int ListWrapper::Insert(ListItem* existing_previous_item, ListItem* new_item)
|
||||
{
|
||||
if (!new_item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Allow existing_previous_item to be NULL if the list is empty.
|
||||
// TODO (hellner) why allow this? Keep it as is for now to avoid
|
||||
// breaking API contract.
|
||||
if (!existing_previous_item && !Empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
if (!existing_previous_item)
|
||||
{
|
||||
PushBackImpl(new_item);
|
||||
return 0;
|
||||
}
|
||||
ListItem* next_item = existing_previous_item->next_;
|
||||
new_item->next_ = existing_previous_item->next_;
|
||||
new_item->prev_ = existing_previous_item;
|
||||
existing_previous_item->next_ = new_item;
|
||||
if (next_item)
|
||||
{
|
||||
next_item->prev_ = new_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_ = new_item;
|
||||
}
|
||||
size_++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::InsertBefore(ListItem* existing_next_item,
|
||||
ListItem* new_item)
|
||||
{
|
||||
if (!new_item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Allow existing_next_item to be NULL if the list is empty.
|
||||
// Todo: why allow this? Keep it as is for now to avoid breaking API
|
||||
// contract.
|
||||
if (!existing_next_item && !Empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
if (!existing_next_item)
|
||||
{
|
||||
PushBackImpl(new_item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListItem* previous_item = existing_next_item->prev_;
|
||||
new_item->next_ = existing_next_item;
|
||||
new_item->prev_ = previous_item;
|
||||
existing_next_item->prev_ = new_item;
|
||||
if (previous_item)
|
||||
{
|
||||
previous_item->next_ = new_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_ = new_item;
|
||||
}
|
||||
size_++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::Erase(ListItem* item)
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
size_--;
|
||||
ListItem* previous_item = item->prev_;
|
||||
ListItem* next_item = item->next_;
|
||||
if (!previous_item)
|
||||
{
|
||||
if(next_item)
|
||||
{
|
||||
next_item->prev_ = 0;
|
||||
}
|
||||
first_ = next_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_item->next_ = next_item;
|
||||
}
|
||||
if (!next_item)
|
||||
{
|
||||
if(previous_item)
|
||||
{
|
||||
previous_item->next_ = 0;
|
||||
}
|
||||
last_ = previous_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_item->prev_ = previous_item;
|
||||
}
|
||||
delete item;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ListWrapper::PushBackImpl(ListItem* item)
|
||||
{
|
||||
if (Empty())
|
||||
{
|
||||
first_ = item;
|
||||
last_ = item;
|
||||
size_++;
|
||||
return;
|
||||
}
|
||||
|
||||
item->prev_ = last_;
|
||||
last_->next_ = item;
|
||||
last_ = item;
|
||||
size_++;
|
||||
}
|
||||
|
||||
void ListWrapper::PushFrontImpl(ListItem* item)
|
||||
{
|
||||
if (Empty())
|
||||
{
|
||||
first_ = item;
|
||||
last_ = item;
|
||||
size_++;
|
||||
return;
|
||||
}
|
||||
|
||||
item->next_ = first_;
|
||||
first_->prev_ = item;
|
||||
first_ = item;
|
||||
size_++;
|
||||
}
|
||||
} //namespace webrtc
|
79
system_wrappers/source/list_no_stl.h
Normal file
79
system_wrappers/source/list_no_stl.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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_LIST_NO_STL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_LIST_NO_STL_H_
|
||||
|
||||
#include "constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class ListNoStlItem
|
||||
{
|
||||
public:
|
||||
ListNoStlItem(const void* ptr);
|
||||
ListNoStlItem(const unsigned int item);
|
||||
virtual ~ListNoStlItem();
|
||||
void* GetItem() const;
|
||||
unsigned int GetUnsignedItem() const;
|
||||
|
||||
protected:
|
||||
ListNoStlItem* next_;
|
||||
ListNoStlItem* prev_;
|
||||
|
||||
private:
|
||||
friend class ListNoStl;
|
||||
|
||||
const void* item_ptr_;
|
||||
const unsigned int item_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListNoStlItem);
|
||||
};
|
||||
|
||||
|
||||
class ListNoStl
|
||||
{
|
||||
public:
|
||||
ListNoStl();
|
||||
virtual ~ListNoStl();
|
||||
|
||||
// ListWrapper functions
|
||||
unsigned int GetSize() const;
|
||||
int PushBack(const void* ptr);
|
||||
int PushBack(const unsigned int item_id);
|
||||
int PushFront(const void* ptr);
|
||||
int PushFront(const unsigned int item_id);
|
||||
int PopFront();
|
||||
int PopBack();
|
||||
bool Empty() const;
|
||||
ListNoStlItem* First() const;
|
||||
ListNoStlItem* Last() const;
|
||||
ListNoStlItem* Next(ListNoStlItem* item) const;
|
||||
ListNoStlItem* Previous(ListNoStlItem* item) const;
|
||||
int Erase(ListNoStlItem* item);
|
||||
int Insert(ListNoStlItem* existing_previous_item,
|
||||
ListNoStlItem* new_item);
|
||||
|
||||
int InsertBefore(ListNoStlItem* existing_next_item,
|
||||
ListNoStlItem* new_item);
|
||||
|
||||
private:
|
||||
void PushBack(ListNoStlItem* item);
|
||||
void PushFront(ListNoStlItem* item);
|
||||
|
||||
CriticalSectionWrapper* critical_section_;
|
||||
ListNoStlItem* first_;
|
||||
ListNoStlItem* last_;
|
||||
unsigned int size_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListNoStl);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_LIST_NO_STL_H_
|
244
system_wrappers/source/list_stl.cc
Normal file
244
system_wrappers/source/list_stl.cc
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 "list_wrapper.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
ListItem::ListItem(const void* item)
|
||||
: this_iter_(),
|
||||
item_ptr_(item),
|
||||
item_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ListItem::ListItem(const unsigned int item)
|
||||
: this_iter_(),
|
||||
item_ptr_(0),
|
||||
item_(item)
|
||||
{
|
||||
}
|
||||
|
||||
ListItem::~ListItem()
|
||||
{
|
||||
}
|
||||
|
||||
void* ListItem::GetItem() const
|
||||
{
|
||||
return const_cast<void*>(item_ptr_);
|
||||
}
|
||||
|
||||
unsigned int ListItem::GetUnsignedItem() const
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
|
||||
ListWrapper::ListWrapper() : list_()
|
||||
{
|
||||
}
|
||||
|
||||
ListWrapper::~ListWrapper()
|
||||
{
|
||||
if (!Empty())
|
||||
{
|
||||
// TODO (hellner) I'm not sure this loggin is useful.
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
|
||||
"Potential memory leak in ListWrapper");
|
||||
// Remove all remaining list items.
|
||||
while (Erase(First()) == 0)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
bool ListWrapper::Empty() const
|
||||
{
|
||||
return list_.empty();
|
||||
}
|
||||
|
||||
unsigned int ListWrapper::GetSize() const
|
||||
{
|
||||
return list_.size();
|
||||
}
|
||||
|
||||
int ListWrapper::PushBack(const void* ptr)
|
||||
{
|
||||
ListItem* item = new ListItem(ptr);
|
||||
list_.push_back(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushBack(const unsigned int item_id)
|
||||
{
|
||||
ListItem* item = new ListItem(item_id);
|
||||
list_.push_back(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushFront(const unsigned int item_id)
|
||||
{
|
||||
ListItem* item = new ListItem(item_id);
|
||||
list_.push_front(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PushFront(const void* ptr)
|
||||
{
|
||||
ListItem* item = new ListItem(ptr);
|
||||
list_.push_front(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PopFront()
|
||||
{
|
||||
if(list_.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
list_.pop_front();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::PopBack()
|
||||
{
|
||||
if(list_.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
list_.pop_back();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::First() const
|
||||
{
|
||||
if(list_.empty())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
std::list<ListItem*>::iterator item_iter = list_.begin();
|
||||
ListItem* return_item = (*item_iter);
|
||||
return_item->this_iter_ = item_iter;
|
||||
return return_item;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Last() const
|
||||
{
|
||||
if(list_.empty())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
// std::list::end() addresses the last item + 1. Decrement so that the
|
||||
// actual last is accessed.
|
||||
std::list<ListItem*>::iterator item_iter = list_.end();
|
||||
--item_iter;
|
||||
ListItem* return_item = (*item_iter);
|
||||
return_item->this_iter_ = item_iter;
|
||||
return return_item;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Next(ListItem* item) const
|
||||
{
|
||||
if(item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
std::list<ListItem*>::iterator item_iter = item->this_iter_;
|
||||
++item_iter;
|
||||
if (item_iter == list_.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ListItem* return_item = (*item_iter);
|
||||
return_item->this_iter_ = item_iter;
|
||||
return return_item;
|
||||
}
|
||||
|
||||
ListItem* ListWrapper::Previous(ListItem* item) const
|
||||
{
|
||||
if(item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
std::list<ListItem*>::iterator item_iter = item->this_iter_;
|
||||
if (item_iter == list_.begin())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
--item_iter;
|
||||
ListItem* return_item = (*item_iter);
|
||||
return_item->this_iter_ = item_iter;
|
||||
return return_item;
|
||||
}
|
||||
|
||||
int ListWrapper::Insert(ListItem* existing_previous_item,
|
||||
ListItem* new_item)
|
||||
{
|
||||
// Allow existingPreviousItem to be NULL if the list is empty.
|
||||
// TODO (hellner) why allow this? Keep it as is for now to avoid
|
||||
// breaking API contract.
|
||||
if (!existing_previous_item && !Empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!new_item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::list<ListItem*>::iterator insert_location = list_.begin();
|
||||
if (!Empty())
|
||||
{
|
||||
insert_location = existing_previous_item->this_iter_;
|
||||
if(insert_location != list_.end())
|
||||
{
|
||||
++insert_location;
|
||||
}
|
||||
}
|
||||
|
||||
list_.insert(insert_location,new_item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::InsertBefore(ListItem* existing_next_item,
|
||||
ListItem* new_item)
|
||||
{
|
||||
// Allow existing_next_item to be NULL if the list is empty.
|
||||
// Todo: why allow this? Keep it as is for now to avoid breaking API
|
||||
// contract.
|
||||
if (!existing_next_item && !Empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!new_item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::list<ListItem*>::iterator insert_location = list_.begin();
|
||||
if (!Empty())
|
||||
{
|
||||
insert_location = existing_next_item->this_iter_;
|
||||
}
|
||||
|
||||
list_.insert(insert_location,new_item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListWrapper::Erase(ListItem* item)
|
||||
{
|
||||
if(item == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
list_.erase(item->this_iter_);
|
||||
return 0;
|
||||
}
|
||||
} // namespace webrtc
|
66
system_wrappers/source/list_stl.h
Normal file
66
system_wrappers/source/list_stl.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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_LIST_STL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_LIST_STL_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
class ListItem
|
||||
{
|
||||
friend class ListWrapper;
|
||||
|
||||
public:
|
||||
ListItem(const void* ptr);
|
||||
ListItem(const unsigned int item);
|
||||
virtual ~ListItem();
|
||||
void* GetItem() const;
|
||||
unsigned int GetUnsignedItem() const;
|
||||
|
||||
private:
|
||||
mutable std::list<ListItem*>::iterator this_iter_;
|
||||
const void* item_ptr_;
|
||||
const unsigned int item_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListItem);
|
||||
};
|
||||
|
||||
class ListWrapper
|
||||
{
|
||||
public:
|
||||
ListWrapper();
|
||||
~ListWrapper();
|
||||
|
||||
// ListWrapper functions
|
||||
unsigned int GetSize() const;
|
||||
int PushBack(const void* ptr);
|
||||
int PushBack(const unsigned int item_id);
|
||||
int PushFront(const void* ptr);
|
||||
int PushFront(const unsigned int item_id);
|
||||
int PopFront();
|
||||
int PopBack();
|
||||
bool Empty() const;
|
||||
ListItem* First() const;
|
||||
ListItem* Last() const;
|
||||
ListItem* Next(ListItem* item) const;
|
||||
ListItem* Previous(ListItem* item) const;
|
||||
int Erase(ListItem* item);
|
||||
int Insert(ListItem* existing_previous_item, ListItem* new_item);
|
||||
int InsertBefore(ListItem* existing_next_item, ListItem* new_item);
|
||||
|
||||
private:
|
||||
mutable std::list<ListItem*> list_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ListWrapper);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_LIST_STL_H_
|
166
system_wrappers/source/map.cc
Normal file
166
system_wrappers/source/map.cc
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 "map_wrapper.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
MapItem::MapItem(int id, void* item) : item_pointer_(item), item_id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
MapItem::~MapItem()
|
||||
{
|
||||
}
|
||||
|
||||
void* MapItem::GetItem()
|
||||
{
|
||||
return item_pointer_;
|
||||
}
|
||||
|
||||
int MapItem::GetId()
|
||||
{
|
||||
return item_id_;
|
||||
}
|
||||
|
||||
unsigned int MapItem::GetUnsignedId()
|
||||
{
|
||||
return static_cast<unsigned int>(item_id_);
|
||||
}
|
||||
|
||||
void MapItem::SetItem(void* ptr)
|
||||
{
|
||||
item_pointer_ = ptr;
|
||||
}
|
||||
|
||||
MapWrapper::MapWrapper() : map_()
|
||||
{
|
||||
}
|
||||
|
||||
MapWrapper::~MapWrapper()
|
||||
{
|
||||
if (!map_.empty())
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
|
||||
"Potential memory leak in MapWrapper");
|
||||
// Remove all map items. Please note that std::map::clear() can't be
|
||||
// used because each item has some dynamically allocated memory
|
||||
// associated with it (i.e. using std::map::clear would introduce a
|
||||
// memory leak).
|
||||
while (Erase(First()) == 0)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
int MapWrapper::Size() const
|
||||
{
|
||||
return (int)map_.size();
|
||||
}
|
||||
|
||||
int MapWrapper::Insert(int id, void* ptr)
|
||||
{
|
||||
map_[id] = new MapItem(id,ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapItem* MapWrapper::First() const
|
||||
{
|
||||
std::map<int, MapItem*>::const_iterator it = map_.begin();
|
||||
if (it != map_.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapItem* MapWrapper::Last() const
|
||||
{
|
||||
std::map<int, MapItem*>::const_reverse_iterator it = map_.rbegin();
|
||||
if (it != map_.rend())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapItem* MapWrapper::Next(MapItem* item) const
|
||||
{
|
||||
if (item == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
std::map<int, MapItem*>::const_iterator it = map_.find(item->item_id_);
|
||||
if (it != map_.end())
|
||||
{
|
||||
it++;
|
||||
if (it != map_.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapItem* MapWrapper::Previous(MapItem* item) const
|
||||
{
|
||||
if (item == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<int, MapItem*>::const_iterator it = map_.find(item->item_id_);
|
||||
if ((it != map_.end()) &&
|
||||
(it != map_.begin()))
|
||||
{
|
||||
--it;
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapItem* MapWrapper::Find(int id) const
|
||||
{
|
||||
std::map<int, MapItem*>::const_iterator it = map_.find(id);
|
||||
if (it != map_.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MapWrapper::Erase(MapItem* item)
|
||||
{
|
||||
if (item == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
std::map<int, MapItem*>::iterator it = map_.find(item->item_id_);
|
||||
if (it != map_.end())
|
||||
{
|
||||
delete it->second;
|
||||
map_.erase(it);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MapWrapper::Erase(const int id)
|
||||
{
|
||||
std::map<int, MapItem*>::iterator it = map_.find(id);
|
||||
if (it != map_.end())
|
||||
{
|
||||
delete it->second;
|
||||
map_.erase(it);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} // namespace webrtc
|
217
system_wrappers/source/map_no_stl.cc
Normal file
217
system_wrappers/source/map_no_stl.cc
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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 "map_no_stl.h"
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
MapNoStlItem::MapNoStlItem(int id, void* item)
|
||||
: next_(0),
|
||||
prev_(0),
|
||||
item_id_(id),
|
||||
item_ptr_(item)
|
||||
{
|
||||
}
|
||||
|
||||
MapNoStlItem::~MapNoStlItem()
|
||||
{
|
||||
}
|
||||
|
||||
void* MapNoStlItem::GetItem()
|
||||
{
|
||||
return item_ptr_;
|
||||
}
|
||||
|
||||
int MapNoStlItem::GetId()
|
||||
{
|
||||
return item_id_;
|
||||
}
|
||||
|
||||
unsigned int MapNoStlItem::GetUnsignedId()
|
||||
{
|
||||
return static_cast<unsigned int>(item_id_);
|
||||
}
|
||||
|
||||
void MapNoStlItem::SetItem(void* ptr)
|
||||
{
|
||||
item_ptr_ = ptr;
|
||||
}
|
||||
|
||||
MapNoStl::MapNoStl()
|
||||
: critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
first_(0),
|
||||
last_(0),
|
||||
size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
MapNoStl::~MapNoStl()
|
||||
{
|
||||
if (First())
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
|
||||
"Potential memory leak in MapNoStl");
|
||||
while (Erase(First()) == 0)
|
||||
{}
|
||||
}
|
||||
delete critical_section_;
|
||||
}
|
||||
|
||||
int MapNoStl::Size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
int MapNoStl::Insert(int id, void* ptr)
|
||||
{
|
||||
MapNoStlItem* new_item = new MapNoStlItem(id, ptr);
|
||||
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
MapNoStlItem* item = first_;
|
||||
size_++;
|
||||
if (!item)
|
||||
{
|
||||
first_ = new_item;
|
||||
last_ = new_item;
|
||||
return 0;
|
||||
}
|
||||
while(item->next_)
|
||||
{
|
||||
// Three scenarios
|
||||
// 1. Item should be inserted first.
|
||||
// 2. Item should be inserted between two items
|
||||
// 3. Item should be inserted last
|
||||
if (item->GetId() > id)
|
||||
{
|
||||
new_item->next_ = item;
|
||||
item->prev_ = new_item;
|
||||
if (item == first_)
|
||||
{
|
||||
first_ = new_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_item->prev_ = item->prev_;
|
||||
new_item->prev_->next_ = new_item;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
item = item->next_;
|
||||
}
|
||||
// 3
|
||||
item->next_ = new_item;
|
||||
new_item->prev_ = item;
|
||||
last_ = new_item;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::First() const
|
||||
{
|
||||
return first_;
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::Last() const
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::Next(MapNoStlItem* item) const
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return item->next_;
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::Previous(MapNoStlItem* item) const
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return item->prev_;
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::Find(int id) const
|
||||
{
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
MapNoStlItem* item = Locate(id);
|
||||
return item;
|
||||
}
|
||||
|
||||
int MapNoStl::Erase(MapNoStlItem* item)
|
||||
{
|
||||
if(!item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
return Remove(item);
|
||||
}
|
||||
|
||||
int MapNoStl::Erase(const int id)
|
||||
{
|
||||
CriticalSectionScoped lock(*critical_section_);
|
||||
MapNoStlItem* item = Locate(id);
|
||||
if(!item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return Remove(item);
|
||||
}
|
||||
|
||||
MapNoStlItem* MapNoStl::Locate(int id) const
|
||||
{
|
||||
MapNoStlItem* item = first_;
|
||||
while(item)
|
||||
{
|
||||
if (item->GetId() == id)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
item = item->next_;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MapNoStl::Remove(MapNoStlItem* item)
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
size_--;
|
||||
MapNoStlItem* previous_item = item->prev_;
|
||||
MapNoStlItem* next_item = item->next_;
|
||||
if (!previous_item)
|
||||
{
|
||||
next_item->prev_ = 0;
|
||||
first_ = next_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_item->next_ = next_item;
|
||||
}
|
||||
if (!next_item)
|
||||
{
|
||||
previous_item->next_ = 0;
|
||||
last_ = previous_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_item->prev_ = previous_item;
|
||||
}
|
||||
delete item;
|
||||
return 0;
|
||||
}
|
||||
} // namespace webrtc
|
70
system_wrappers/source/map_no_stl.h
Normal file
70
system_wrappers/source/map_no_stl.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_MAP_NO_STL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_MAP_NO_STL_H_
|
||||
|
||||
#include "constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class MapNoStlItem
|
||||
{
|
||||
friend class Map;
|
||||
|
||||
public:
|
||||
MapNoStlItem(int id, void* ptr);
|
||||
virtual ~MapNoStlItem();
|
||||
void* GetItem();
|
||||
int GetId();
|
||||
unsigned int GetUnsignedId();
|
||||
void SetItem(void* ptr);
|
||||
|
||||
protected:
|
||||
MapNoStlItem* next_;
|
||||
MapNoStlItem* prev_;
|
||||
|
||||
private:
|
||||
int item_id_;
|
||||
void* item_ptr_;
|
||||
DISALLOW_COPY_AND_ASSIGN(MapNoStlItem);
|
||||
};
|
||||
|
||||
class MapNoStl
|
||||
{
|
||||
public:
|
||||
MapNoStl();
|
||||
virtual ~MapNoStl();
|
||||
|
||||
// MapWrapper functions.
|
||||
int Insert(int id, void* ptr);
|
||||
int Erase(MapNoStlItem* item);
|
||||
int Erase(int id);
|
||||
int Size() const;
|
||||
MapNoStlItem* First() const;
|
||||
MapNoStlItem* Last() const;
|
||||
MapNoStlItem* Next(MapNoStlItem* item) const;
|
||||
MapNoStlItem* Previous(MapNoStlItem* item) const;
|
||||
MapNoStlItem* Find(int id) const;
|
||||
|
||||
private:
|
||||
MapNoStlItem* Locate(int id) const;
|
||||
int Remove(MapNoStlItem* item);
|
||||
|
||||
CriticalSection* critical_section_;
|
||||
MapNoStlItem* first_;
|
||||
MapNoStlItem* last_;
|
||||
int size_;
|
||||
DISALLOW_COPY_AND_ASSIGN(MapNoStl);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_MAP_NO_STL_H_
|
46
system_wrappers/source/rw_lock.cc
Normal file
46
system_wrappers/source/rw_lock.cc
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rw_lock_wrapper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "rw_lock_windows.h"
|
||||
#elif defined(ANDROID)
|
||||
#include <stdlib.h>
|
||||
#include "rw_lock_generic.h"
|
||||
#else
|
||||
#include "rw_lock_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
RWLockWrapper* RWLockWrapper::CreateRWLock()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
RWLockWrapper* lock = new RWLockWindows();
|
||||
#elif defined(ANDROID)
|
||||
RWLockWrapper* lock = new RWLockWrapperGeneric();
|
||||
#else
|
||||
RWLockWrapper* lock = new RWLockLinux();
|
||||
#endif
|
||||
if(lock->Init() != 0)
|
||||
{
|
||||
delete lock;
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
RWLockWrapper::~RWLockWrapper()
|
||||
{
|
||||
}
|
||||
} // namespace webrtc
|
106
system_wrappers/source/rw_lock_generic.cc
Normal file
106
system_wrappers/source/rw_lock_generic.cc
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 "rw_lock_generic.h"
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
RWLockWrapperGeneric::RWLockWrapperGeneric()
|
||||
: _readersActive(0),
|
||||
_writerActive(false),
|
||||
_readersWaiting(0),
|
||||
_writersWaiting(0)
|
||||
{
|
||||
_critSectPtr = CriticalSectionWrapper::CreateCriticalSection();
|
||||
_readCondPtr = ConditionVariableWrapper::CreateConditionVariable();
|
||||
_writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
|
||||
}
|
||||
|
||||
RWLockWrapperGeneric::~RWLockWrapperGeneric()
|
||||
{
|
||||
delete _writeCondPtr;
|
||||
delete _readCondPtr;
|
||||
delete _critSectPtr;
|
||||
}
|
||||
|
||||
int RWLockWrapperGeneric::Init()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RWLockWrapperGeneric::AcquireLockExclusive()
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
|
||||
if (_writerActive || _readersActive > 0)
|
||||
{
|
||||
++_writersWaiting;
|
||||
|
||||
while (_writerActive || _readersActive > 0)
|
||||
{
|
||||
_writeCondPtr->SleepCS(*_critSectPtr);
|
||||
}
|
||||
|
||||
--_writersWaiting;
|
||||
}
|
||||
_writerActive = true;
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
|
||||
void RWLockWrapperGeneric::ReleaseLockExclusive()
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
|
||||
_writerActive = false;
|
||||
|
||||
if (_writersWaiting > 0)
|
||||
{
|
||||
_writeCondPtr->Wake();
|
||||
|
||||
}else if (_readersWaiting > 0)
|
||||
{
|
||||
_readCondPtr->WakeAll();
|
||||
}
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
|
||||
void RWLockWrapperGeneric::AcquireLockShared()
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
|
||||
if (_writerActive || _writersWaiting > 0)
|
||||
{
|
||||
++_readersWaiting;
|
||||
|
||||
while (_writerActive || _writersWaiting > 0)
|
||||
{
|
||||
_readCondPtr->SleepCS(*_critSectPtr);
|
||||
}
|
||||
--_readersWaiting;
|
||||
}
|
||||
++_readersActive;
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
|
||||
void RWLockWrapperGeneric::ReleaseLockShared()
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
|
||||
--_readersActive;
|
||||
|
||||
if (_readersActive == 0 && _writersWaiting > 0)
|
||||
{
|
||||
_writeCondPtr->Wake();
|
||||
}
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
} // namespace webrtc
|
46
system_wrappers/source/rw_lock_generic.h
Normal file
46
system_wrappers/source/rw_lock_generic.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
||||
|
||||
#include "rw_lock_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
class RWLockWrapperGeneric : public RWLockWrapper
|
||||
{
|
||||
public:
|
||||
RWLockWrapperGeneric();
|
||||
virtual ~RWLockWrapperGeneric();
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
protected:
|
||||
virtual int Init();
|
||||
|
||||
private:
|
||||
CriticalSectionWrapper* _critSectPtr;
|
||||
ConditionVariableWrapper* _readCondPtr;
|
||||
ConditionVariableWrapper* _writeCondPtr;
|
||||
|
||||
int _readersActive;
|
||||
bool _writerActive;
|
||||
int _readersWaiting;
|
||||
int _writersWaiting;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
|
47
system_wrappers/source/rw_lock_linux.cc
Normal file
47
system_wrappers/source/rw_lock_linux.cc
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 "rw_lock_linux.h"
|
||||
|
||||
namespace webrtc {
|
||||
RWLockLinux::RWLockLinux() : _lock()
|
||||
{
|
||||
}
|
||||
|
||||
RWLockLinux::~RWLockLinux()
|
||||
{
|
||||
pthread_rwlock_destroy(&_lock);
|
||||
}
|
||||
|
||||
int RWLockLinux::Init()
|
||||
{
|
||||
return pthread_rwlock_init(&_lock, 0);
|
||||
}
|
||||
|
||||
void RWLockLinux::AcquireLockExclusive()
|
||||
{
|
||||
pthread_rwlock_wrlock(&_lock);
|
||||
}
|
||||
|
||||
void RWLockLinux::ReleaseLockExclusive()
|
||||
{
|
||||
pthread_rwlock_unlock(&_lock);
|
||||
}
|
||||
|
||||
void RWLockLinux::AcquireLockShared()
|
||||
{
|
||||
pthread_rwlock_rdlock(&_lock);
|
||||
}
|
||||
|
||||
void RWLockLinux::ReleaseLockShared()
|
||||
{
|
||||
pthread_rwlock_unlock(&_lock);
|
||||
}
|
||||
} // namespace webrtc
|
39
system_wrappers/source/rw_lock_linux.h
Normal file
39
system_wrappers/source/rw_lock_linux.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_LINUX_H_
|
||||
|
||||
#include "rw_lock_wrapper.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
class RWLockLinux : public RWLockWrapper
|
||||
{
|
||||
public:
|
||||
RWLockLinux();
|
||||
virtual ~RWLockLinux();
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
protected:
|
||||
virtual int Init();
|
||||
|
||||
private:
|
||||
pthread_rwlock_t _lock;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_LINUX_H_
|
186
system_wrappers/source/rw_lock_windows.cc
Normal file
186
system_wrappers/source/rw_lock_windows.cc
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 "rw_lock_windows.h"
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "trace.h"
|
||||
|
||||
// TODO (hellner) why not just use the rw_lock_generic.cc solution if
|
||||
// native is not supported? Unnecessary redundancy!
|
||||
|
||||
namespace webrtc {
|
||||
bool RWLockWindows::_winSupportRWLockPrimitive = false;
|
||||
static HMODULE library = NULL;
|
||||
|
||||
PInitializeSRWLock _PInitializeSRWLock;
|
||||
PAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
|
||||
PAcquireSRWLockShared _PAcquireSRWLockShared;
|
||||
PReleaseSRWLockShared _PReleaseSRWLockShared;
|
||||
PReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
|
||||
|
||||
RWLockWindows::RWLockWindows()
|
||||
: _critSectPtr(NULL),
|
||||
_readCondPtr(NULL),
|
||||
_writeCondPtr(NULL),
|
||||
_readersActive(0),
|
||||
_writerActive(false),
|
||||
_readersWaiting(0),
|
||||
_writersWaiting(0)
|
||||
{
|
||||
}
|
||||
|
||||
RWLockWindows::~RWLockWindows()
|
||||
{
|
||||
delete _writeCondPtr;
|
||||
delete _readCondPtr;
|
||||
delete _critSectPtr;
|
||||
}
|
||||
|
||||
int RWLockWindows::Init()
|
||||
{
|
||||
if(!library)
|
||||
{
|
||||
// Use native implementation if supported (i.e Vista+)
|
||||
library = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if(library)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded Kernel.dll");
|
||||
|
||||
_PInitializeSRWLock =
|
||||
(PInitializeSRWLock)GetProcAddress(
|
||||
library,
|
||||
"InitializeSRWLock");
|
||||
|
||||
_PAcquireSRWLockExclusive =
|
||||
(PAcquireSRWLockExclusive)GetProcAddress(
|
||||
library,
|
||||
"AcquireSRWLockExclusive");
|
||||
_PReleaseSRWLockExclusive =
|
||||
(PReleaseSRWLockExclusive)GetProcAddress(
|
||||
library,
|
||||
"ReleaseSRWLockExclusive");
|
||||
_PAcquireSRWLockShared =
|
||||
(PAcquireSRWLockShared)GetProcAddress(
|
||||
library,
|
||||
"AcquireSRWLockShared");
|
||||
_PReleaseSRWLockShared =
|
||||
(PReleaseSRWLockShared)GetProcAddress(
|
||||
library,
|
||||
"ReleaseSRWLockShared");
|
||||
|
||||
if( _PInitializeSRWLock &&
|
||||
_PAcquireSRWLockExclusive &&
|
||||
_PReleaseSRWLockExclusive &&
|
||||
_PAcquireSRWLockShared &&
|
||||
_PReleaseSRWLockShared )
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Loaded Simple RW Lock");
|
||||
_winSupportRWLockPrimitive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_winSupportRWLockPrimitive)
|
||||
{
|
||||
_PInitializeSRWLock(&_lock);
|
||||
} else {
|
||||
_critSectPtr = CriticalSectionWrapper::CreateCriticalSection();
|
||||
_readCondPtr = ConditionVariableWrapper::CreateConditionVariable();
|
||||
_writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RWLockWindows::AcquireLockExclusive()
|
||||
{
|
||||
if (_winSupportRWLockPrimitive)
|
||||
{
|
||||
_PAcquireSRWLockExclusive(&_lock);
|
||||
} else {
|
||||
_critSectPtr->Enter();
|
||||
|
||||
if (_writerActive || _readersActive > 0)
|
||||
{
|
||||
++_writersWaiting;
|
||||
while (_writerActive || _readersActive > 0)
|
||||
{
|
||||
_writeCondPtr->SleepCS(*_critSectPtr);
|
||||
}
|
||||
--_writersWaiting;
|
||||
}
|
||||
_writerActive = true;
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockWindows::ReleaseLockExclusive()
|
||||
{
|
||||
if(_winSupportRWLockPrimitive)
|
||||
{
|
||||
_PReleaseSRWLockExclusive(&_lock);
|
||||
} else {
|
||||
_critSectPtr->Enter();
|
||||
_writerActive = false;
|
||||
if (_writersWaiting > 0)
|
||||
{
|
||||
_writeCondPtr->Wake();
|
||||
|
||||
}else if (_readersWaiting > 0) {
|
||||
_readCondPtr->WakeAll();
|
||||
}
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockWindows::AcquireLockShared()
|
||||
{
|
||||
if(_winSupportRWLockPrimitive)
|
||||
{
|
||||
_PAcquireSRWLockShared(&_lock);
|
||||
} else
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
if (_writerActive || _writersWaiting > 0)
|
||||
{
|
||||
++_readersWaiting;
|
||||
|
||||
while (_writerActive || _writersWaiting > 0)
|
||||
{
|
||||
_readCondPtr->SleepCS(*_critSectPtr);
|
||||
}
|
||||
--_readersWaiting;
|
||||
}
|
||||
++_readersActive;
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
}
|
||||
|
||||
void RWLockWindows::ReleaseLockShared()
|
||||
{
|
||||
if(_winSupportRWLockPrimitive)
|
||||
{
|
||||
_PReleaseSRWLockShared(&_lock);
|
||||
} else
|
||||
{
|
||||
_critSectPtr->Enter();
|
||||
|
||||
--_readersActive;
|
||||
|
||||
if (_readersActive == 0 && _writersWaiting > 0)
|
||||
{
|
||||
_writeCondPtr->Wake();
|
||||
}
|
||||
_critSectPtr->Leave();
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
71
system_wrappers/source/rw_lock_windows.h
Normal file
71
system_wrappers/source/rw_lock_windows.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
|
||||
|
||||
#include "rw_lock_wrapper.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#if !defined(RTL_SRWLOCK_INIT)
|
||||
typedef struct _RTL_SRWLOCK
|
||||
{
|
||||
void* Ptr;
|
||||
} RTL_SRWLOCK, *PRTL_SRWLOCK;
|
||||
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
typedef void (WINAPI *PInitializeSRWLock)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI *PAcquireSRWLockExclusive)(PSRWLOCK);
|
||||
typedef void (WINAPI *PReleaseSRWLockExclusive)(PSRWLOCK);
|
||||
|
||||
typedef void (WINAPI *PAcquireSRWLockShared)(PSRWLOCK);
|
||||
typedef void (WINAPI *PReleaseSRWLockShared)(PSRWLOCK);
|
||||
|
||||
|
||||
class RWLockWindows :public RWLockWrapper
|
||||
{
|
||||
public:
|
||||
RWLockWindows();
|
||||
virtual ~RWLockWindows();
|
||||
|
||||
virtual void AcquireLockExclusive();
|
||||
virtual void ReleaseLockExclusive();
|
||||
|
||||
virtual void AcquireLockShared();
|
||||
virtual void ReleaseLockShared();
|
||||
|
||||
protected:
|
||||
virtual int Init();
|
||||
|
||||
private:
|
||||
// For native implementation.
|
||||
static bool _winSupportRWLockPrimitive;
|
||||
SRWLOCK _lock;
|
||||
|
||||
// Genric implementation, fallback if native is not supported.
|
||||
CriticalSectionWrapper* _critSectPtr;
|
||||
ConditionVariableWrapper* _readCondPtr;
|
||||
ConditionVariableWrapper* _writeCondPtr;
|
||||
|
||||
int _readersActive;
|
||||
bool _writerActive;
|
||||
int _readersWaiting;
|
||||
int _writersWaiting;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
|
551
system_wrappers/source/sort.cc
Normal file
551
system_wrappers/source/sort.cc
Normal file
@ -0,0 +1,551 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// When the platform supports STL, the functions are implemented using a
|
||||
// templated spreadsort algorithm (http://sourceforge.net/projects/spreadsort/),
|
||||
// part of the Boost C++ library collection. Otherwise, the C standard library's
|
||||
// qsort() will be used.
|
||||
|
||||
#include "sort.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring> // memcpy
|
||||
#include <new> // nothrow new
|
||||
|
||||
#ifdef NO_STL
|
||||
#include <cstdlib> // qsort
|
||||
#else
|
||||
#include <algorithm> // std::sort
|
||||
#include <vector>
|
||||
#include "spreadsort.hpp" // TODO (ajm) upgrade to spreadsortv2.
|
||||
#endif
|
||||
|
||||
#ifdef NO_STL
|
||||
#define COMPARE_DEREFERENCED(XT, YT) \
|
||||
do \
|
||||
{ \
|
||||
if ((XT) > (YT)) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
else if ((XT) < (YT)) \
|
||||
{ \
|
||||
return -1; \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define COMPARE_FOR_QSORT(X, Y, TYPE) \
|
||||
do \
|
||||
{ \
|
||||
TYPE xT = static_cast<TYPE>(*static_cast<const TYPE*>(X)); \
|
||||
TYPE yT = static_cast<TYPE>(*static_cast<const TYPE*>(Y)); \
|
||||
COMPARE_DEREFERENCED(xT, yT); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define COMPARE_KEY_FOR_QSORT(SORT_KEY_X, SORT_KEY_Y, TYPE) \
|
||||
do \
|
||||
{ \
|
||||
TYPE xT = static_cast<TYPE>(*static_cast<TYPE*> \
|
||||
(static_cast<const SortKey*>(SORT_KEY_X)->key)); \
|
||||
TYPE yT = static_cast<TYPE>(*static_cast<TYPE*> \
|
||||
(static_cast<const SortKey*>(SORT_KEY_Y)->key)); \
|
||||
COMPARE_DEREFERENCED(xT, yT); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define KEY_QSORT(SORT_KEY, KEY, NUM_OF_ELEMENTS, KEY_TYPE, COMPARE_FUNC) \
|
||||
do \
|
||||
{ \
|
||||
KEY_TYPE* keyT = (KEY_TYPE*)(key); \
|
||||
for (WebRtc_UWord32 i = 0; i < (NUM_OF_ELEMENTS); i++) \
|
||||
{ \
|
||||
ptrSortKey[i].key = &keyT[i]; \
|
||||
ptrSortKey[i].index = i; \
|
||||
} \
|
||||
\
|
||||
qsort((SORT_KEY), (NUM_OF_ELEMENTS), sizeof(SortKey), (COMPARE_FUNC));\
|
||||
} \
|
||||
while(0)
|
||||
#endif
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
#ifdef NO_STL
|
||||
struct SortKey
|
||||
{
|
||||
void* key;
|
||||
WebRtc_UWord32 index;
|
||||
};
|
||||
#else
|
||||
template<typename KeyType>
|
||||
struct SortKey
|
||||
{
|
||||
KeyType key;
|
||||
WebRtc_UWord32 index;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace // Unnamed namespace provides internal linkage.
|
||||
{
|
||||
#ifdef NO_STL
|
||||
int CompareWord8(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_Word8);
|
||||
}
|
||||
|
||||
int CompareUWord8(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_UWord8);
|
||||
}
|
||||
|
||||
int CompareWord16(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_Word16);
|
||||
}
|
||||
|
||||
int CompareUWord16(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_UWord16);
|
||||
}
|
||||
|
||||
int CompareWord32(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_Word32);
|
||||
}
|
||||
|
||||
int CompareUWord32(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_UWord32);
|
||||
}
|
||||
|
||||
int CompareWord64(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_Word64);
|
||||
}
|
||||
|
||||
int CompareUWord64(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, WebRtc_UWord64);
|
||||
}
|
||||
|
||||
int CompareFloat32(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, float);
|
||||
}
|
||||
|
||||
int CompareFloat64(const void* x, const void* y)
|
||||
{
|
||||
COMPARE_FOR_QSORT(x, y, double);
|
||||
}
|
||||
|
||||
int CompareKeyWord8(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_Word8);
|
||||
}
|
||||
|
||||
int CompareKeyUWord8(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_UWord8);
|
||||
}
|
||||
|
||||
int CompareKeyWord16(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_Word16);
|
||||
}
|
||||
|
||||
int CompareKeyUWord16(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_UWord16);
|
||||
}
|
||||
|
||||
int CompareKeyWord32(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_Word32);
|
||||
}
|
||||
|
||||
int CompareKeyUWord32(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_UWord32);
|
||||
}
|
||||
|
||||
int CompareKeyWord64(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_Word64);
|
||||
}
|
||||
|
||||
int CompareKeyUWord64(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, WebRtc_UWord64);
|
||||
}
|
||||
|
||||
int CompareKeyFloat32(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, float);
|
||||
}
|
||||
|
||||
int CompareKeyFloat64(const void* sortKeyX, const void* sortKeyY)
|
||||
{
|
||||
COMPARE_KEY_FOR_QSORT(sortKeyX, sortKeyY, double);
|
||||
}
|
||||
#else
|
||||
template <typename KeyType>
|
||||
struct KeyLessThan
|
||||
{
|
||||
bool operator()(const SortKey<KeyType>& sortKeyX,
|
||||
const SortKey<KeyType>& sortKeyY) const
|
||||
{
|
||||
return sortKeyX.key < sortKeyY.key;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename KeyType>
|
||||
struct KeyRightShift
|
||||
{
|
||||
KeyType operator()(const SortKey<KeyType>& sortKey,
|
||||
const unsigned offset) const
|
||||
{
|
||||
return sortKey.key >> offset;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DataType>
|
||||
inline void IntegerSort(void* data, WebRtc_UWord32 numOfElements)
|
||||
{
|
||||
DataType* dataT = static_cast<DataType*>(data);
|
||||
boost::integer_sort(dataT, dataT + numOfElements);
|
||||
}
|
||||
|
||||
template <typename DataType, typename IntegerType>
|
||||
inline void FloatSort(void* data, WebRtc_UWord32 numOfElements)
|
||||
{
|
||||
DataType* dataT = static_cast<DataType*>(data);
|
||||
IntegerType cVal = 0;
|
||||
boost::float_sort_cast(dataT, dataT + numOfElements, cVal);
|
||||
}
|
||||
|
||||
template <typename DataType>
|
||||
inline void StdSort(void* data, WebRtc_UWord32 numOfElements)
|
||||
{
|
||||
DataType* dataT = static_cast<DataType*>(data);
|
||||
std::sort(dataT, dataT + numOfElements);
|
||||
}
|
||||
|
||||
template<typename KeyType>
|
||||
inline WebRtc_Word32 SetupKeySort(void* key,
|
||||
SortKey<KeyType>*& ptrSortKey,
|
||||
WebRtc_UWord32 numOfElements)
|
||||
{
|
||||
ptrSortKey = new(std::nothrow) SortKey<KeyType>[numOfElements];
|
||||
if (ptrSortKey == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
KeyType* keyT = static_cast<KeyType*>(key);
|
||||
for (WebRtc_UWord32 i = 0; i < numOfElements; i++)
|
||||
{
|
||||
ptrSortKey[i].key = keyT[i];
|
||||
ptrSortKey[i].index = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename KeyType>
|
||||
inline WebRtc_Word32 TeardownKeySort(void* data,
|
||||
SortKey<KeyType>* ptrSortKey,
|
||||
WebRtc_UWord32 numOfElements, WebRtc_UWord32 sizeOfElement)
|
||||
{
|
||||
WebRtc_UWord8* ptrData = static_cast<WebRtc_UWord8*>(data);
|
||||
WebRtc_UWord8* ptrDataSorted = new(std::nothrow) WebRtc_UWord8
|
||||
[numOfElements * sizeOfElement];
|
||||
if (ptrDataSorted == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i < numOfElements; i++)
|
||||
{
|
||||
memcpy(ptrDataSorted + i * sizeOfElement, ptrData +
|
||||
ptrSortKey[i].index * sizeOfElement, sizeOfElement);
|
||||
}
|
||||
memcpy(ptrData, ptrDataSorted, numOfElements * sizeOfElement);
|
||||
delete[] ptrSortKey;
|
||||
delete[] ptrDataSorted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename KeyType>
|
||||
inline WebRtc_Word32 IntegerKeySort(void* data, void* key,
|
||||
WebRtc_UWord32 numOfElements,
|
||||
WebRtc_UWord32 sizeOfElement)
|
||||
{
|
||||
SortKey<KeyType>* ptrSortKey;
|
||||
if (SetupKeySort<KeyType>(key, ptrSortKey, numOfElements) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
boost::integer_sort(ptrSortKey, ptrSortKey + numOfElements,
|
||||
KeyRightShift<KeyType>(), KeyLessThan<KeyType>());
|
||||
|
||||
if (TeardownKeySort<KeyType>(data, ptrSortKey, numOfElements,
|
||||
sizeOfElement) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename KeyType>
|
||||
inline WebRtc_Word32 StdKeySort(void* data, void* key,
|
||||
WebRtc_UWord32 numOfElements,
|
||||
WebRtc_UWord32 sizeOfElement)
|
||||
{
|
||||
SortKey<KeyType>* ptrSortKey;
|
||||
if (SetupKeySort<KeyType>(key, ptrSortKey, numOfElements) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::sort(ptrSortKey, ptrSortKey + numOfElements,
|
||||
KeyLessThan<KeyType>());
|
||||
|
||||
if (TeardownKeySort<KeyType>(data, ptrSortKey, numOfElements,
|
||||
sizeOfElement) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WebRtc_Word32 Sort(void* data, WebRtc_UWord32 numOfElements, Type type)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef NO_STL
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_Word8:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_Word8), CompareWord8);
|
||||
break;
|
||||
case TYPE_UWord8:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_UWord8), CompareUWord8);
|
||||
break;
|
||||
case TYPE_Word16:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_Word16), CompareWord16);
|
||||
break;
|
||||
case TYPE_UWord16:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_UWord16), CompareUWord16);
|
||||
break;
|
||||
case TYPE_Word32:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_Word32), CompareWord32);
|
||||
break;
|
||||
case TYPE_UWord32:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_UWord32), CompareUWord32);
|
||||
break;
|
||||
case TYPE_Word64:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_Word64), CompareWord64);
|
||||
break;
|
||||
case TYPE_UWord64:
|
||||
qsort(data, numOfElements, sizeof(WebRtc_UWord64), CompareUWord64);
|
||||
break;
|
||||
case TYPE_Float32:
|
||||
qsort(data, numOfElements, sizeof(float), CompareFloat32);
|
||||
break;
|
||||
case TYPE_Float64:
|
||||
qsort(data, numOfElements, sizeof(double), CompareFloat64);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
// Fall back to std::sort for 64-bit types and floats due to compiler
|
||||
// warnings and VS 2003 build crashes respectively with spreadsort.
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_Word8:
|
||||
IntegerSort<WebRtc_Word8>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_UWord8:
|
||||
IntegerSort<WebRtc_UWord8>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_Word16:
|
||||
IntegerSort<WebRtc_Word16>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_UWord16:
|
||||
IntegerSort<WebRtc_UWord16>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_Word32:
|
||||
IntegerSort<WebRtc_Word32>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_UWord32:
|
||||
IntegerSort<WebRtc_UWord32>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_Word64:
|
||||
StdSort<WebRtc_Word64>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_UWord64:
|
||||
StdSort<WebRtc_UWord64>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_Float32:
|
||||
StdSort<float>(data, numOfElements);
|
||||
break;
|
||||
case TYPE_Float64:
|
||||
StdSort<double>(data, numOfElements);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 KeySort(void* data, void* key, WebRtc_UWord32 numOfElements,
|
||||
WebRtc_UWord32 sizeOfElement, Type keyType)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((WebRtc_UWord64)numOfElements * sizeOfElement > 0xffffffff)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef NO_STL
|
||||
SortKey* ptrSortKey = new(std::nothrow) SortKey[numOfElements];
|
||||
if (ptrSortKey == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (keyType)
|
||||
{
|
||||
case TYPE_Word8:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_Word8,
|
||||
CompareKeyWord8);
|
||||
break;
|
||||
case TYPE_UWord8:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_UWord8,
|
||||
CompareKeyUWord8);
|
||||
break;
|
||||
case TYPE_Word16:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_Word16,
|
||||
CompareKeyWord16);
|
||||
break;
|
||||
case TYPE_UWord16:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_UWord16,
|
||||
CompareKeyUWord16);
|
||||
break;
|
||||
case TYPE_Word32:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_Word32,
|
||||
CompareKeyWord32);
|
||||
break;
|
||||
case TYPE_UWord32:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_UWord32,
|
||||
CompareKeyUWord32);
|
||||
break;
|
||||
case TYPE_Word64:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_Word64,
|
||||
CompareKeyWord64);
|
||||
break;
|
||||
case TYPE_UWord64:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, WebRtc_UWord64,
|
||||
CompareKeyUWord64);
|
||||
break;
|
||||
case TYPE_Float32:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, float,
|
||||
CompareKeyFloat32);
|
||||
break;
|
||||
case TYPE_Float64:
|
||||
KEY_QSORT(ptrSortKey, key, numOfElements, double,
|
||||
CompareKeyFloat64);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Shuffle into sorted position based on index map.
|
||||
WebRtc_UWord8* ptrData = static_cast<WebRtc_UWord8*>(data);
|
||||
WebRtc_UWord8* ptrDataSorted = new(std::nothrow) WebRtc_UWord8
|
||||
[numOfElements * sizeOfElement];
|
||||
if (ptrDataSorted == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i < numOfElements; i++)
|
||||
{
|
||||
memcpy(ptrDataSorted + i * sizeOfElement, ptrData +
|
||||
ptrSortKey[i].index * sizeOfElement, sizeOfElement);
|
||||
}
|
||||
memcpy(ptrData, ptrDataSorted, numOfElements * sizeOfElement);
|
||||
|
||||
delete[] ptrSortKey;
|
||||
delete[] ptrDataSorted;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
// Fall back to std::sort for 64-bit types and floats due to compiler
|
||||
// warnings and errors respectively with spreadsort.
|
||||
switch (keyType)
|
||||
{
|
||||
case TYPE_Word8:
|
||||
return IntegerKeySort<WebRtc_Word8>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_UWord8:
|
||||
return IntegerKeySort<WebRtc_UWord8>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_Word16:
|
||||
return IntegerKeySort<WebRtc_Word16>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_UWord16:
|
||||
return IntegerKeySort<WebRtc_UWord16>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_Word32:
|
||||
return IntegerKeySort<WebRtc_Word32>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_UWord32:
|
||||
return IntegerKeySort<WebRtc_UWord32>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_Word64:
|
||||
return StdKeySort<WebRtc_Word64>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_UWord64:
|
||||
return StdKeySort<WebRtc_UWord64>(data, key, numOfElements,
|
||||
sizeOfElement);
|
||||
case TYPE_Float32:
|
||||
return StdKeySort<float>(data, key, numOfElements, sizeOfElement);
|
||||
case TYPE_Float64:
|
||||
return StdKeySort<double>(data, key, numOfElements, sizeOfElement);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
42
system_wrappers/source/spreadsortlib/constants.hpp
Normal file
42
system_wrappers/source/spreadsortlib/constants.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.*/
|
||||
#ifndef BOOST_SPREADSORT_CONSTANTS
|
||||
#define BOOST_SPREADSORT_CONSTANTS
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
//Tuning constants
|
||||
//Sets the minimum number of items per bin.
|
||||
static const unsigned LOG_MEAN_BIN_SIZE = 2;
|
||||
//This should be tuned to your processor cache; if you go too large you get cache misses on bins
|
||||
//The smaller this number, the less worst-case memory usage. If too small, too many recursions slow down spreadsort
|
||||
static const unsigned MAX_SPLITS = 10;
|
||||
//Used to force a comparison-based sorting for small bins, if it's faster. Minimum value 0
|
||||
static const unsigned LOG_MIN_SPLIT_COUNT = 5;
|
||||
//There is a minimum size below which it is not worth using spreadsort
|
||||
static const long MIN_SORT_SIZE = 1000;
|
||||
//This is the constant on the log base n of m calculation; make this larger the faster std::sort is relative to spreadsort
|
||||
static const unsigned LOG_CONST = 2;
|
||||
}
|
||||
}
|
||||
#endif
|
1688
system_wrappers/source/spreadsortlib/spreadsort.hpp
Normal file
1688
system_wrappers/source/spreadsortlib/spreadsort.hpp
Normal file
File diff suppressed because it is too large
Load Diff
146
system_wrappers/source/system_wrappers.gyp
Normal file
146
system_wrappers/source/system_wrappers.gyp
Normal file
@ -0,0 +1,146 @@
|
||||
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# TODO: Rename files to use *_linux.cpp etc. names, to automatically include relevant files. Remove conditions section.
|
||||
|
||||
{
|
||||
'includes': [
|
||||
'../../common_settings.gypi', # Common settings
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'system_wrappers',
|
||||
'type': '<(library)',
|
||||
'include_dirs': [
|
||||
'spreadsortlib',
|
||||
'../interface',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
],
|
||||
},
|
||||
'sources': [
|
||||
'../interface/aligned_malloc.h',
|
||||
'../interface/atomic32_wrapper.h',
|
||||
'../interface/condition_variable_wrapper.h',
|
||||
'../interface/cpu_wrapper.h',
|
||||
'../interface/cpu_features_wrapper.h',
|
||||
'../interface/critical_section_wrapper.h',
|
||||
'../interface/event_wrapper.h',
|
||||
'../interface/file_wrapper.h',
|
||||
'../interface/list_wrapper.h',
|
||||
'../interface/map_wrapper.h',
|
||||
'../interface/rw_lock_wrapper.h',
|
||||
'../interface/sort.h',
|
||||
'../interface/thread_wrapper.h',
|
||||
'../interface/tick_util.h',
|
||||
'../interface/trace.h',
|
||||
'aligned_malloc.cc',
|
||||
'atomic32.cc',
|
||||
'atomic32_linux.h',
|
||||
'atomic32_mac.h',
|
||||
'atomic32_windows.h',
|
||||
'condition_variable.cc',
|
||||
'condition_variable_linux.h',
|
||||
'condition_variable_windows.h',
|
||||
'cpu.cc',
|
||||
'cpu_linux.h',
|
||||
'cpu_mac.h',
|
||||
'cpu_windows.h',
|
||||
'cpu_features.cc',
|
||||
'critical_section.cc',
|
||||
'critical_section_linux.h',
|
||||
'critical_section_windows.h',
|
||||
'event.cc',
|
||||
'event_linux.h',
|
||||
'event_windows.h',
|
||||
'file_impl.cc',
|
||||
'file_impl.h',
|
||||
'list_no_stl.cc',
|
||||
'map.cc',
|
||||
'rw_lock.cc',
|
||||
'rw_lock_linux.h',
|
||||
'rw_lock_windows.h',
|
||||
'sort.cc',
|
||||
'thread.cc',
|
||||
'thread_linux.h',
|
||||
'thread_windows.h',
|
||||
'trace_impl.cc',
|
||||
'trace_impl.h',
|
||||
'trace_linux.h',
|
||||
'trace_windows.h',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'sources': [
|
||||
'condition_variable_linux.cc',
|
||||
'cpu_linux.cc',
|
||||
'critical_section_linux.cc',
|
||||
'event_linux.cc',
|
||||
'thread_linux.cc',
|
||||
'trace_linux.cc',
|
||||
'rw_lock_linux.cc',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lrt',
|
||||
],
|
||||
},
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'sources': [
|
||||
'condition_variable_linux.cc',
|
||||
'cpu_mac.cc',
|
||||
'critical_section_linux.cc',
|
||||
'event_linux.cc',
|
||||
'rw_lock_linux.cc',
|
||||
'thread_linux.cc',
|
||||
'trace_linux.cc',
|
||||
],
|
||||
}],
|
||||
['OS=="win"', {
|
||||
'sources': [
|
||||
'atomic32_windows.h',
|
||||
'condition_variable_windows.cc',
|
||||
'condition_variable_windows.h',
|
||||
'cpu_windows.cc',
|
||||
'cpu_windows.h',
|
||||
'critical_section_windows.cc',
|
||||
'critical_section_windows.h',
|
||||
'event_windows.cc',
|
||||
'event_windows.h',
|
||||
'rw_lock_windows.cc',
|
||||
'rw_lock_windows.h',
|
||||
'thread_windows.cc',
|
||||
'thread_windows.h',
|
||||
'trace_windows.cc',
|
||||
'trace_windows.h',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lwinmm.lib',
|
||||
],
|
||||
},
|
||||
}],
|
||||
] # conditions
|
||||
},
|
||||
{
|
||||
'target_name': 'system_wrappersTest',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'system_wrappers'
|
||||
],
|
||||
'sources': [
|
||||
'../test/Test.cpp',
|
||||
],
|
||||
},
|
||||
], # targets
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:2
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
30
system_wrappers/source/thread.cc
Normal file
30
system_wrappers/source/thread.cc
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 "thread_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "thread_windows.h"
|
||||
#else
|
||||
#include "thread_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
ThreadWrapper* ThreadWrapper::CreateThread(ThreadRunFunction func,
|
||||
ThreadObj obj, ThreadPriority prio,
|
||||
const char* threadName)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return new ThreadWindows(func, obj, prio, threadName);
|
||||
#else
|
||||
return ThreadLinux::Create(func, obj, prio, threadName);
|
||||
#endif
|
||||
}
|
||||
} // namespace webrtc
|
340
system_wrappers/source/thread_linux.cc
Normal file
340
system_wrappers/source/thread_linux.cc
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* 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 "thread_linux.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h> // strncpy
|
||||
#include <time.h> // nanosleep
|
||||
#include <unistd.h>
|
||||
#ifdef WEBRTC_LINUX
|
||||
#include <sys/types.h>
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include "event_wrapper.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
extern "C"
|
||||
{
|
||||
static void* StartThread(void* lpParameter)
|
||||
{
|
||||
static_cast<ThreadLinux*>(lpParameter)->Run();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(WEBRTC_LINUX) && !defined(ANDROID))
|
||||
static pid_t gettid()
|
||||
{
|
||||
#if defined(__NR_gettid)
|
||||
return syscall(__NR_gettid);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ThreadWrapper* ThreadLinux::Create(ThreadRunFunction func, ThreadObj obj,
|
||||
ThreadPriority prio, const char* threadName)
|
||||
{
|
||||
ThreadLinux* ptr = new ThreadLinux(func, obj, prio, threadName);
|
||||
if (!ptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
const int error = ptr->Construct();
|
||||
if (error)
|
||||
{
|
||||
delete ptr;
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ThreadLinux::ThreadLinux(ThreadRunFunction func, ThreadObj obj,
|
||||
ThreadPriority prio, const char* threadName)
|
||||
: _runFunction(func),
|
||||
_obj(obj),
|
||||
_alive(false),
|
||||
_dead(true),
|
||||
_prio(prio),
|
||||
_event(EventWrapper::Create()),
|
||||
_setThreadName(false)
|
||||
{
|
||||
#ifdef WEBRTC_LINUX
|
||||
_linuxPid = -1;
|
||||
#endif
|
||||
if (threadName != NULL)
|
||||
{
|
||||
_setThreadName = true;
|
||||
strncpy(_name, threadName, kThreadMaxNameLength);
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadLinux::Construct()
|
||||
{
|
||||
int result = 0;
|
||||
#if !defined(ANDROID)
|
||||
// Enable immediate cancellation if requested, see Shutdown()
|
||||
result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
result = pthread_attr_init(&_attr);
|
||||
if (result != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadLinux::~ThreadLinux()
|
||||
{
|
||||
pthread_attr_destroy(&_attr);
|
||||
delete _event;
|
||||
}
|
||||
|
||||
#define HAS_THREAD_ID !defined(MAC_IPHONE) && !defined(MAC_IPHONE_SIM) && \
|
||||
!defined(WEBRTC_MAC) && !defined(WEBRTC_MAC_INTEL) && \
|
||||
!defined(MAC_DYLIB) && !defined(MAC_INTEL_DYLIB)
|
||||
#if HAS_THREAD_ID
|
||||
bool ThreadLinux::Start(unsigned int& threadID)
|
||||
#else
|
||||
bool ThreadLinux::Start(unsigned int& /*threadID*/)
|
||||
#endif
|
||||
{
|
||||
if (!_runFunction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int result = pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED);
|
||||
// Set the stack stack size to 1M.
|
||||
result |= pthread_attr_setstacksize(&_attr, 1024*1024);
|
||||
#ifdef WEBRTC_THREAD_RR
|
||||
const int policy = SCHED_RR;
|
||||
#else
|
||||
const int policy = SCHED_FIFO;
|
||||
#endif
|
||||
_event->Reset();
|
||||
result |= pthread_create(&_thread, &_attr, &StartThread, this);
|
||||
if (result != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait up to 10 seconds for the OS to call the callback function. Prevents
|
||||
// race condition if Stop() is called too quickly after start.
|
||||
if (kEventSignaled != _event->Wait(WEBRTC_EVENT_10_SEC))
|
||||
{
|
||||
// Timed out. Something went wrong.
|
||||
_runFunction = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if HAS_THREAD_ID
|
||||
threadID = static_cast<unsigned int>(_thread);
|
||||
#endif
|
||||
sched_param param;
|
||||
|
||||
const int minPrio = sched_get_priority_min(policy);
|
||||
const int maxPrio = sched_get_priority_max(policy);
|
||||
if ((minPrio == EINVAL) || (maxPrio == EINVAL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_prio)
|
||||
{
|
||||
case kLowPriority:
|
||||
param.sched_priority = minPrio + 1;
|
||||
break;
|
||||
case kNormalPriority:
|
||||
param.sched_priority = (minPrio + maxPrio) / 2;
|
||||
break;
|
||||
case kHighPriority:
|
||||
param.sched_priority = maxPrio - 3;
|
||||
break;
|
||||
case kHighestPriority:
|
||||
param.sched_priority = maxPrio - 2;
|
||||
break;
|
||||
case kRealtimePriority:
|
||||
param.sched_priority = maxPrio - 1;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
result = pthread_setschedparam(_thread, policy, ¶m);
|
||||
if (result == EINVAL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (defined(WEBRTC_LINUX) && !defined(ANDROID))
|
||||
bool ThreadLinux::SetAffinity(const int* processorNumbers,
|
||||
const unsigned int amountOfProcessors)
|
||||
{
|
||||
if (!processorNumbers || (amountOfProcessors == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
|
||||
for(unsigned int processor = 0;
|
||||
processor < amountOfProcessors;
|
||||
processor++)
|
||||
{
|
||||
CPU_SET(processorNumbers[processor], &mask);
|
||||
}
|
||||
const int result = sched_setaffinity(_linuxPid, (unsigned int)sizeof(mask),
|
||||
&mask);
|
||||
if (result != 0)
|
||||
{
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// NOTE: On Mac OS X, use the Thread affinity API in
|
||||
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
|
||||
// instead of Linux gettid() syscall.
|
||||
bool ThreadLinux::SetAffinity(const int* , const unsigned int)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ThreadLinux::SetNotAlive()
|
||||
{
|
||||
_alive = false;
|
||||
}
|
||||
|
||||
bool ThreadLinux::Shutdown()
|
||||
{
|
||||
#if !defined(ANDROID)
|
||||
if (_thread && (0 != pthread_cancel(_thread)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ThreadLinux::Stop()
|
||||
{
|
||||
_alive = false;
|
||||
|
||||
// TODO (hellner) why not use an event here?
|
||||
// Wait up to 10 seconds for the thread to terminate
|
||||
for (int i = 0; i < 1000 && !_dead; i++)
|
||||
{
|
||||
timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 10*1000*1000;
|
||||
nanosleep(&t, NULL);
|
||||
}
|
||||
if (_dead)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadLinux::Run()
|
||||
{
|
||||
_alive = true;
|
||||
_dead = false;
|
||||
#ifdef WEBRTC_LINUX
|
||||
if(_linuxPid == -1)
|
||||
{
|
||||
_linuxPid = gettid();
|
||||
}
|
||||
#endif
|
||||
// The event the Start() is waiting for.
|
||||
_event->Set();
|
||||
|
||||
if (_setThreadName)
|
||||
{
|
||||
#ifdef WEBRTC_LINUX
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
|
||||
"Thread with id:%d name:%s started ", _linuxPid, _name);
|
||||
prctl(PR_SET_NAME, (unsigned long)_name, 0, 0, 0);
|
||||
#else
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
|
||||
"Thread with name:%s started ", _name);
|
||||
#endif
|
||||
}else
|
||||
{
|
||||
#ifdef WEBRTC_LINUX
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Thread with id:%d without name started", _linuxPid);
|
||||
#else
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
|
||||
"Thread without name started");
|
||||
#endif
|
||||
}
|
||||
do
|
||||
{
|
||||
if (_runFunction)
|
||||
{
|
||||
if (!_runFunction(_obj))
|
||||
{
|
||||
_alive = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_alive = false;
|
||||
}
|
||||
}
|
||||
while (_alive);
|
||||
|
||||
if (_setThreadName)
|
||||
{
|
||||
// Don't set the name for the trace thread because it may cause a
|
||||
// deadlock. TODO (hellner) there should be a better solution than
|
||||
// coupling the thread and the trace class like this.
|
||||
if (strcmp(_name, "Trace"))
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
|
||||
"Thread with name:%s stopped", _name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
|
||||
"Thread without name stopped");
|
||||
}
|
||||
_dead = true;
|
||||
}
|
||||
} // namespace webrtc
|
69
system_wrappers/source/thread_linux.h
Normal file
69
system_wrappers/source/thread_linux.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_LINUX_H_
|
||||
|
||||
#include "thread_wrapper.h"
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
class EventWrapper;
|
||||
|
||||
class ThreadLinux : public ThreadWrapper
|
||||
{
|
||||
public:
|
||||
static ThreadWrapper* Create(ThreadRunFunction func, ThreadObj obj,
|
||||
ThreadPriority prio, const char* threadName);
|
||||
|
||||
ThreadLinux(ThreadRunFunction func, ThreadObj obj, ThreadPriority prio,
|
||||
const char* threadName);
|
||||
~ThreadLinux();
|
||||
|
||||
// From ThreadWrapper
|
||||
virtual void SetNotAlive();
|
||||
virtual bool Start(unsigned int& id);
|
||||
// Not implemented on Mac
|
||||
virtual bool SetAffinity(const int* processorNumbers,
|
||||
unsigned int amountOfProcessors);
|
||||
virtual bool Stop();
|
||||
virtual bool Shutdown();
|
||||
|
||||
void Run();
|
||||
|
||||
private:
|
||||
int Construct();
|
||||
|
||||
private:
|
||||
// processing function
|
||||
ThreadRunFunction _runFunction;
|
||||
ThreadObj _obj;
|
||||
|
||||
// internal state
|
||||
bool _alive;
|
||||
bool _dead;
|
||||
ThreadPriority _prio;
|
||||
EventWrapper* _event;
|
||||
|
||||
// zero-terminated thread name string
|
||||
char _name[kThreadMaxNameLength];
|
||||
bool _setThreadName;
|
||||
|
||||
// handle to thread
|
||||
pthread_attr_t _attr;
|
||||
pthread_t _thread;
|
||||
#ifdef WEBRTC_LINUX
|
||||
pid_t _linuxPid;
|
||||
#endif
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_LINUX_H_
|
234
system_wrappers/source/thread_windows.cc
Normal file
234
system_wrappers/source/thread_windows.cc
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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 "thread_windows.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "thread_windows_set_name.h"
|
||||
#include "trace.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
// VS 2005: Disable warnings for default initialized arrays.
|
||||
#pragma warning(disable:4351)
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
ThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
|
||||
ThreadPriority prio, const char* threadName)
|
||||
: ThreadWrapper(),
|
||||
_runFunction(func),
|
||||
_obj(obj),
|
||||
_alive(false),
|
||||
_dead(true),
|
||||
_doNotCloseHandle(false),
|
||||
_prio(prio),
|
||||
_event(NULL),
|
||||
_thread(NULL),
|
||||
_id(0),
|
||||
_name(),
|
||||
_setThreadName(false)
|
||||
{
|
||||
_event = EventWrapper::Create();
|
||||
_critsectStop = CriticalSectionWrapper::CreateCriticalSection();
|
||||
if (threadName != NULL)
|
||||
{
|
||||
// Set the thread name to appear in the VS debugger.
|
||||
_setThreadName = true;
|
||||
strncpy(_name, threadName, kThreadMaxNameLength);
|
||||
}
|
||||
}
|
||||
|
||||
ThreadWindows::~ThreadWindows()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(!_alive);
|
||||
#endif
|
||||
if (_thread)
|
||||
{
|
||||
CloseHandle(_thread);
|
||||
}
|
||||
if(_event)
|
||||
{
|
||||
delete _event;
|
||||
}
|
||||
if(_critsectStop)
|
||||
{
|
||||
delete _critsectStop;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter)
|
||||
{
|
||||
static_cast<ThreadWindows*>(lpParameter)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Start(unsigned int& threadID)
|
||||
{
|
||||
_doNotCloseHandle = false;
|
||||
|
||||
// Set stack size to 1M
|
||||
_thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0,
|
||||
&threadID);
|
||||
if(_thread == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_id = threadID;
|
||||
_event->Wait(INFINITE);
|
||||
|
||||
switch(_prio)
|
||||
{
|
||||
case kLowPriority:
|
||||
SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
|
||||
break;
|
||||
case kNormalPriority:
|
||||
SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
|
||||
break;
|
||||
case kHighPriority:
|
||||
SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
break;
|
||||
case kHighestPriority:
|
||||
SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
|
||||
break;
|
||||
case kRealtimePriority:
|
||||
SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
break;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadWindows::SetAffinity(const int* processorNumbers,
|
||||
const unsigned int amountOfProcessors)
|
||||
{
|
||||
DWORD_PTR processorBitMask = 0;
|
||||
for(unsigned int processorIndex = 0;
|
||||
processorIndex < amountOfProcessors;
|
||||
processorIndex++)
|
||||
{
|
||||
// Convert from an array with processor numbers to a bitmask
|
||||
// Processor numbers start at zero.
|
||||
// TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='?
|
||||
// Or even better |=
|
||||
processorBitMask = 1 << processorNumbers[processorIndex];
|
||||
}
|
||||
return SetThreadAffinityMask(_thread,processorBitMask) != 0;
|
||||
}
|
||||
|
||||
void ThreadWindows::SetNotAlive()
|
||||
{
|
||||
_alive = false;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Shutdown()
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
BOOL ret = TRUE;
|
||||
if (_thread)
|
||||
{
|
||||
ret = TerminateThread(_thread, exitCode);
|
||||
_alive = false;
|
||||
_dead = true;
|
||||
_thread = NULL;
|
||||
}
|
||||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool ThreadWindows::Stop()
|
||||
{
|
||||
_critsectStop->Enter();
|
||||
// Prevents the handle from being closed in ThreadWindows::Run()
|
||||
_doNotCloseHandle = true;
|
||||
_alive = false;
|
||||
bool signaled = false;
|
||||
if (_thread && !_dead)
|
||||
{
|
||||
_critsectStop->Leave();
|
||||
// Wait up to 2 seconds for the thread to complete.
|
||||
if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000))
|
||||
{
|
||||
signaled = true;
|
||||
}
|
||||
_critsectStop->Enter();
|
||||
}
|
||||
if (_thread)
|
||||
{
|
||||
CloseHandle(_thread);
|
||||
_thread = NULL;
|
||||
}
|
||||
_critsectStop->Leave();
|
||||
|
||||
if (_dead || signaled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadWindows::Run()
|
||||
{
|
||||
_alive = true;
|
||||
_dead = false;
|
||||
_event->Set();
|
||||
|
||||
// All tracing must be after _event->Set to avoid deadlock in Trace.
|
||||
if (_setThreadName)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
|
||||
"Thread with name:%s started ", _name);
|
||||
SetThreadName(-1, _name); // -1, set thread name for the calling thread.
|
||||
}else
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
|
||||
"Thread without name started");
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (_runFunction)
|
||||
{
|
||||
if (!_runFunction(_obj))
|
||||
{
|
||||
_alive = false;
|
||||
}
|
||||
} else {
|
||||
_alive = false;
|
||||
}
|
||||
} while(_alive);
|
||||
|
||||
if (_setThreadName)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
|
||||
"Thread with name:%s stopped", _name);
|
||||
} else {
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id,
|
||||
"Thread without name stopped");
|
||||
}
|
||||
|
||||
_critsectStop->Enter();
|
||||
|
||||
if (_thread && !_doNotCloseHandle)
|
||||
{
|
||||
HANDLE thread = _thread;
|
||||
_thread = NULL;
|
||||
CloseHandle(thread);
|
||||
}
|
||||
_dead = true;
|
||||
|
||||
_critsectStop->Leave();
|
||||
};
|
||||
} // namespace webrtc
|
66
system_wrappers/source/thread_windows.h
Normal file
66
system_wrappers/source/thread_windows.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
|
||||
|
||||
#include "thread_wrapper.h"
|
||||
#include "event_wrapper.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ThreadWindows : public ThreadWrapper
|
||||
{
|
||||
public:
|
||||
ThreadWindows(ThreadRunFunction func, ThreadObj obj, ThreadPriority prio,
|
||||
const char* threadName);
|
||||
virtual ~ThreadWindows();
|
||||
|
||||
virtual bool Start(unsigned int& id);
|
||||
bool SetAffinity(const int* processorNumbers,
|
||||
const unsigned int amountOfProcessors);
|
||||
virtual bool Stop();
|
||||
virtual void SetNotAlive();
|
||||
|
||||
static unsigned int WINAPI StartThread(LPVOID lpParameter);
|
||||
|
||||
virtual bool Shutdown();
|
||||
|
||||
protected:
|
||||
virtual void Run();
|
||||
|
||||
private:
|
||||
ThreadRunFunction _runFunction;
|
||||
ThreadObj _obj;
|
||||
|
||||
bool _alive;
|
||||
bool _dead;
|
||||
|
||||
// TODO (hellner)
|
||||
// _doNotCloseHandle member seem pretty redundant. Should be able to remove
|
||||
// it. Basically it should be fine to reclaim the handle when calling stop
|
||||
// and in the destructor.
|
||||
bool _doNotCloseHandle;
|
||||
ThreadPriority _prio;
|
||||
EventWrapper* _event;
|
||||
CriticalSectionWrapper* _critsectStop;
|
||||
|
||||
HANDLE _thread;
|
||||
unsigned int _id;
|
||||
char _name[kThreadMaxNameLength];
|
||||
bool _setThreadName;
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
|
43
system_wrappers/source/thread_windows_set_name.h
Normal file
43
system_wrappers/source/thread_windows_set_name.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Use of this source code is governed by the MICROSOFT LIMITED PUBLIC LICENSE
|
||||
* copyright license which can be found in the LICENSE file in the
|
||||
* third_party_mods/mslpl directory of the source tree or at
|
||||
* http://msdn.microsoft.com/en-us/cc300389.aspx#P.
|
||||
*/
|
||||
/*
|
||||
* The original code can be found here:
|
||||
* http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct THREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
LPCSTR szName; // pointer to name (in user addr space)
|
||||
DWORD dwThreadID; // thread ID (-1 = caller thread)
|
||||
DWORD dwFlags; // reserved for future use, must be zero
|
||||
};
|
||||
|
||||
void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
|
||||
(ULONG_PTR*)&info);
|
||||
}
|
||||
__except (EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
|
949
system_wrappers/source/trace_impl.cc
Normal file
949
system_wrappers/source/trace_impl.cc
Normal file
@ -0,0 +1,949 @@
|
||||
/*
|
||||
* 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 "trace_impl.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h> // memset
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "trace_windows.h"
|
||||
#include "fix_interlocked_exchange_pointer_windows.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include "trace_linux.h"
|
||||
#endif // _WIN32
|
||||
|
||||
#define KEY_LEN_CHARS 31
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable:4355)
|
||||
// VS 2005: Disable warnings for default initialized arrays.
|
||||
#pragma warning(disable:4351)
|
||||
#endif // _WIN32
|
||||
|
||||
namespace webrtc {
|
||||
static WebRtc_UWord32 levelFilter = kTraceDefault;
|
||||
|
||||
// Construct On First Use idiom. Avoids "static initialization order fiasco".
|
||||
Trace* TraceImpl::StaticInstance(TraceCount inc, const TraceLevel level)
|
||||
{
|
||||
// TODO (hellner): use atomic wrapper instead.
|
||||
static volatile long theTraceCount = 0;
|
||||
static Trace* volatile theTrace = NULL;
|
||||
|
||||
TraceCreate state = WEBRTC_TRACE_EXIST;
|
||||
|
||||
// Sanitys to avoid taking lock unless absolutely necessary (for
|
||||
// performance reasons). inc == WEBRTC_TRACE_INC_NO_CREATE) implies that
|
||||
// a message will be written to file.
|
||||
if(level != kTraceAll && inc == WEBRTC_TRACE_INC_NO_CREATE)
|
||||
{
|
||||
if(!(level & levelFilter))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
// TODO (pwestin): crtiSect is never reclaimed. Fix memory leak.
|
||||
static CriticalSectionWrapper* crtiSect(
|
||||
CriticalSectionWrapper::CreateCriticalSection());
|
||||
CriticalSectionScoped lock(*crtiSect);
|
||||
|
||||
if(inc == WEBRTC_TRACE_INC_NO_CREATE && theTraceCount == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(inc == WEBRTC_TRACE_INC || inc == WEBRTC_TRACE_INC_NO_CREATE)
|
||||
{
|
||||
theTraceCount++;
|
||||
if(theTraceCount == 1)
|
||||
{
|
||||
state = WEBRTC_TRACE_CREATE;
|
||||
}
|
||||
} else {
|
||||
theTraceCount--;
|
||||
if(theTraceCount == 0)
|
||||
{
|
||||
state = WEBRTC_TRACE_DESTROY;
|
||||
}
|
||||
}
|
||||
if(state == WEBRTC_TRACE_CREATE)
|
||||
{
|
||||
theTrace = TraceImpl::CreateTrace();
|
||||
|
||||
} else if(state == WEBRTC_TRACE_DESTROY) {
|
||||
Trace* oldValue = theTrace;
|
||||
theTrace = NULL;
|
||||
// The lock is held by the scoped critical section. Release the lock
|
||||
// temporarily so that the trace can be safely deleted. If the lock
|
||||
// was kept during the delete, e.g. creating and destroying the trace
|
||||
// too quickly may lead to a deadlock.
|
||||
// This is due to the fact that starting and stopping a ThreadWrapper
|
||||
// thread will trigger writing of trace messages.
|
||||
// TODO (hellner): remove the tight coupling with the thread
|
||||
// implementation.
|
||||
crtiSect->Leave();
|
||||
if(oldValue)
|
||||
{
|
||||
delete static_cast<TraceImpl*>(oldValue);
|
||||
}
|
||||
// Re-aqcuire the lock.
|
||||
crtiSect->Enter();
|
||||
return NULL;
|
||||
}
|
||||
#else // _WIN32
|
||||
if(inc == WEBRTC_TRACE_INC_NO_CREATE && theTraceCount == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(inc == WEBRTC_TRACE_INC_NO_CREATE)
|
||||
{
|
||||
if(1 == InterlockedIncrement(&theTraceCount))
|
||||
{
|
||||
// The trace has been destroyed by some other thread. Rollback.
|
||||
InterlockedDecrement(&theTraceCount);
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
// Sanity to catch corrupt state.
|
||||
if(theTrace == NULL)
|
||||
{
|
||||
assert(false);
|
||||
InterlockedDecrement(&theTraceCount);
|
||||
return NULL;
|
||||
}
|
||||
} else if(inc == WEBRTC_TRACE_INC) {
|
||||
if(theTraceCount == 0)
|
||||
{
|
||||
state = WEBRTC_TRACE_CREATE;
|
||||
} else {
|
||||
if(1 == InterlockedIncrement(&theTraceCount))
|
||||
{
|
||||
// InterlockedDecrement because reference count should not be
|
||||
// updated just yet (that's done when the trace is created).
|
||||
InterlockedDecrement(&theTraceCount);
|
||||
state = WEBRTC_TRACE_CREATE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int newValue = InterlockedDecrement(&theTraceCount);
|
||||
if(newValue == 0)
|
||||
{
|
||||
state = WEBRTC_TRACE_DESTROY;
|
||||
}
|
||||
}
|
||||
|
||||
if(state == WEBRTC_TRACE_CREATE)
|
||||
{
|
||||
// Create trace and let whichever thread finishes first assign its local
|
||||
// copy to the global instance. All other threads reclaim their local
|
||||
// copy.
|
||||
Trace* newTrace = TraceImpl::CreateTrace();
|
||||
if(1 == InterlockedIncrement(&theTraceCount))
|
||||
{
|
||||
Trace* oldValue = (Trace*)InterlockedExchangePointer(
|
||||
reinterpret_cast<void* volatile*>(&theTrace), newTrace);
|
||||
assert(oldValue == NULL);
|
||||
assert(theTrace);
|
||||
} else {
|
||||
InterlockedDecrement(&theTraceCount);
|
||||
if(newTrace)
|
||||
{
|
||||
delete static_cast<TraceImpl*>(newTrace);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} else if(state == WEBRTC_TRACE_DESTROY)
|
||||
{
|
||||
Trace* oldValue = (Trace*)InterlockedExchangePointer(
|
||||
reinterpret_cast<void* volatile*>(&theTrace), NULL);
|
||||
if(oldValue)
|
||||
{
|
||||
delete static_cast<TraceImpl*>(oldValue);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif // #ifndef _WIN32
|
||||
return theTrace;
|
||||
}
|
||||
|
||||
void Trace::CreateTrace()
|
||||
{
|
||||
TraceImpl::StaticInstance(WEBRTC_TRACE_INC);
|
||||
}
|
||||
|
||||
void Trace::ReturnTrace()
|
||||
{
|
||||
TraceImpl::StaticInstance(WEBRTC_TRACE_DEC);
|
||||
}
|
||||
|
||||
TraceImpl* TraceImpl::GetTrace(const TraceLevel level)
|
||||
{
|
||||
return (TraceImpl*)StaticInstance(WEBRTC_TRACE_INC_NO_CREATE, level);
|
||||
}
|
||||
|
||||
Trace* TraceImpl::CreateTrace()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return new TraceWindows();
|
||||
#else
|
||||
return new TraceLinux();
|
||||
#endif
|
||||
}
|
||||
|
||||
TraceImpl::TraceImpl()
|
||||
: _critsectInterface(*CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_callback(NULL),
|
||||
_rowCountText(0),
|
||||
_fileCountText(0),
|
||||
_traceFile(*FileWrapper::Create()),
|
||||
_thread(*ThreadWrapper::CreateThread(TraceImpl::Run, this,
|
||||
kHighestPriority, "Trace")),
|
||||
_event(*EventWrapper::Create()),
|
||||
_critsectArray(*CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_nextFreeIdx(),
|
||||
_level(),
|
||||
_length(),
|
||||
_messageQueue(),
|
||||
_activeQueue(0)
|
||||
{
|
||||
_nextFreeIdx[0] = 0;
|
||||
_nextFreeIdx[1] = 0;
|
||||
|
||||
unsigned int tid = 0;
|
||||
_thread.Start(tid);
|
||||
|
||||
for(int m = 0; m < WEBRTC_TRACE_NUM_ARRAY; m++)
|
||||
{
|
||||
for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
|
||||
{
|
||||
_messageQueue[m][n] = new
|
||||
WebRtc_Word8[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TraceImpl::StopThread()
|
||||
{
|
||||
// Release the worker thread so that it can flush any lingering messages.
|
||||
_event.Set();
|
||||
|
||||
// Allow 10 ms for pending messages to be flushed out.
|
||||
// TODO (hellner): why not use condition variables to do this? Or let the
|
||||
// worker thread die and let this thread flush remaining
|
||||
// messages?
|
||||
#ifdef _WIN32
|
||||
Sleep(10);
|
||||
#else
|
||||
timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 10*1000000;
|
||||
nanosleep(&t,NULL);
|
||||
#endif
|
||||
|
||||
_thread.SetNotAlive();
|
||||
// Make sure the thread finishes as quickly as possible (instead of having
|
||||
// to wait for the timeout).
|
||||
_event.Set();
|
||||
bool stopped = _thread.Stop();
|
||||
|
||||
CriticalSectionScoped lock(_critsectInterface);
|
||||
_traceFile.Flush();
|
||||
_traceFile.CloseFile();
|
||||
return stopped;
|
||||
}
|
||||
|
||||
TraceImpl::~TraceImpl()
|
||||
{
|
||||
StopThread();
|
||||
delete &_event;
|
||||
delete &_traceFile;
|
||||
delete &_thread;
|
||||
delete &_critsectInterface;
|
||||
delete &_critsectArray;
|
||||
|
||||
for(int m = 0; m < WEBRTC_TRACE_NUM_ARRAY; m++)
|
||||
{
|
||||
for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
|
||||
{
|
||||
delete [] _messageQueue[m][n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::AddLevel(char* szMessage, const TraceLevel level) const
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case kTraceStateInfo:
|
||||
sprintf (szMessage, "STATEINFO ; ");
|
||||
break;
|
||||
case kTraceWarning:
|
||||
sprintf (szMessage, "WARNING ; ");
|
||||
break;
|
||||
case kTraceError:
|
||||
sprintf (szMessage, "ERROR ; ");
|
||||
break;
|
||||
case kTraceCritical:
|
||||
sprintf (szMessage, "CRITICAL ; ");
|
||||
break;
|
||||
case kTraceInfo:
|
||||
sprintf (szMessage, "DEBUGINFO ; ");
|
||||
break;
|
||||
case kTraceModuleCall:
|
||||
sprintf (szMessage, "MODULECALL; ");
|
||||
break;
|
||||
case kTraceMemory:
|
||||
sprintf (szMessage, "MEMORY ; ");
|
||||
break;
|
||||
case kTraceTimer:
|
||||
sprintf (szMessage, "TIMER ; ");
|
||||
break;
|
||||
case kTraceStream:
|
||||
sprintf (szMessage, "STREAM ; ");
|
||||
break;
|
||||
case kTraceApiCall:
|
||||
sprintf (szMessage, "APICALL ; ");
|
||||
break;
|
||||
case kTraceDebug:
|
||||
sprintf (szMessage, "DEBUG ; ");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
// All messages are 12 characters.
|
||||
return 12;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::AddModuleAndId(char* traceMessage,
|
||||
const TraceModule module,
|
||||
const WebRtc_Word32 id) const
|
||||
{
|
||||
// Use long int to prevent problems with different definitions of
|
||||
// WebRtc_Word32.
|
||||
// TODO (hellner): is this actually a problem? If so, it should be better to
|
||||
// clean up WebRtc_Word32
|
||||
const long int idl = id;
|
||||
if(idl != -1)
|
||||
{
|
||||
const unsigned long int idEngine = id>>16;
|
||||
const unsigned long int idChannel = id & 0xffff;
|
||||
|
||||
switch (module)
|
||||
{
|
||||
case kTraceVoice:
|
||||
sprintf(traceMessage, " VOICE:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf(traceMessage, " VIDEO:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf(traceMessage, " UTILITY:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf(traceMessage, " RTP/RTCP:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf(traceMessage, " TRANSPORT:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf(traceMessage, "AUDIO CODING:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf(traceMessage, " SRTP:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf(traceMessage, " AUDIO MIX/S:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf(traceMessage, " AUDIO MIX/C:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf(traceMessage, "VIDEO CODING:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
// Print sleep time and API call
|
||||
sprintf(traceMessage, " VIDEO MIX:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf(traceMessage, " FILE:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVqe:
|
||||
sprintf(traceMessage, " VQE:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf(traceMessage, "AUDIO DEVICE:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf(traceMessage, "VIDEO RENDER:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf(traceMessage, "VIDEO CAPTUR:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
case kTraceVideoPreocessing:
|
||||
sprintf(traceMessage, " VIDEO PROC:%5ld %5ld;", idEngine,
|
||||
idChannel);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
switch (module)
|
||||
{
|
||||
case kTraceVoice:
|
||||
sprintf (traceMessage, " VOICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideo:
|
||||
sprintf (traceMessage, " VIDEO:%11ld;", idl);
|
||||
break;
|
||||
case kTraceUtility:
|
||||
sprintf (traceMessage, " UTILITY:%11ld;", idl);
|
||||
break;
|
||||
case kTraceRtpRtcp:
|
||||
sprintf (traceMessage, " RTP/RTCP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceTransport:
|
||||
sprintf (traceMessage, " TRANSPORT:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioCoding:
|
||||
sprintf (traceMessage, "AUDIO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceSrtp:
|
||||
sprintf (traceMessage, " SRTP:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerServer:
|
||||
sprintf (traceMessage, " AUDIO MIX/S:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioMixerClient:
|
||||
sprintf (traceMessage, " AUDIO MIX/C:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCoding:
|
||||
sprintf (traceMessage, "VIDEO CODING:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoMixer:
|
||||
sprintf (traceMessage, " VIDEO MIX:%11ld;", idl);
|
||||
break;
|
||||
case kTraceFile:
|
||||
sprintf (traceMessage, " FILE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVqe:
|
||||
sprintf (traceMessage, " VQE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceAudioDevice:
|
||||
sprintf (traceMessage, "AUDIO DEVICE:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoRenderer:
|
||||
sprintf (traceMessage, "VIDEO RENDER:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoCapture:
|
||||
sprintf (traceMessage, "VIDEO CAPTUR:%11ld;", idl);
|
||||
break;
|
||||
case kTraceVideoPreocessing:
|
||||
sprintf (traceMessage, " VIDEO PROC:%11ld;", idl);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// All messages are 25 characters.
|
||||
return 25;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
|
||||
const bool addFileCounter)
|
||||
{
|
||||
CriticalSectionScoped lock(_critsectInterface);
|
||||
|
||||
_traceFile.Flush();
|
||||
_traceFile.CloseFile();
|
||||
|
||||
if(fileNameUTF8)
|
||||
{
|
||||
if(addFileCounter)
|
||||
{
|
||||
_fileCountText = 1;
|
||||
|
||||
WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
|
||||
CreateFileName(fileNameUTF8, fileNameWithCounterUTF8,
|
||||
_fileCountText);
|
||||
if(_traceFile.OpenFile(fileNameWithCounterUTF8, false, false,
|
||||
true) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}else {
|
||||
_fileCountText = 0;
|
||||
if(_traceFile.OpenFile(fileNameUTF8, false, false, true) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_rowCountText = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::TraceFileImpl(
|
||||
WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])
|
||||
{
|
||||
CriticalSectionScoped lock(_critsectInterface);
|
||||
return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize);
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::SetTraceCallbackImpl(TraceCallback* callback)
|
||||
{
|
||||
CriticalSectionScoped lock(_critsectInterface);
|
||||
_callback = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceImpl::AddMessage(
|
||||
char* traceMessage,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const WebRtc_UWord16 writtenSoFar) const
|
||||
|
||||
{
|
||||
int length = 0;
|
||||
if(writtenSoFar >= WEBRTC_TRACE_MAX_MESSAGE_SIZE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// - 2 to leave room for newline and NULL termination
|
||||
#ifdef _WIN32
|
||||
length = _snprintf(traceMessage,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2,
|
||||
"%s",msg);
|
||||
if(length < 0)
|
||||
{
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2;
|
||||
traceMessage[length] = 0;
|
||||
}
|
||||
#else
|
||||
length = snprintf(traceMessage,
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE-writtenSoFar-2, "%s",msg);
|
||||
if(length < 0 || length > WEBRTC_TRACE_MAX_MESSAGE_SIZE-writtenSoFar - 2)
|
||||
{
|
||||
length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2;
|
||||
traceMessage[length] = 0;
|
||||
}
|
||||
#endif
|
||||
// Length with NULL termination.
|
||||
return length+1;
|
||||
}
|
||||
|
||||
void TraceImpl::AddMessageToList(
|
||||
const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const WebRtc_UWord16 length,
|
||||
const TraceLevel level)
|
||||
{
|
||||
CriticalSectionScoped lock(_critsectArray);
|
||||
|
||||
if(_nextFreeIdx[_activeQueue] >= WEBRTC_TRACE_MAX_QUEUE)
|
||||
{
|
||||
if( ! _traceFile.Open() &&
|
||||
!_callback)
|
||||
{
|
||||
// Keep at least the last 1/4 of old messages when not logging.
|
||||
// TODO (hellner): isn't this redundant. The user will make it known
|
||||
// when to start logging. Why keep messages before
|
||||
// that?
|
||||
for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE/4; n++)
|
||||
{
|
||||
const int lastQuarterOffset = (3*WEBRTC_TRACE_MAX_QUEUE/4);
|
||||
memcpy(_messageQueue[_activeQueue][n],
|
||||
_messageQueue[_activeQueue][n + lastQuarterOffset],
|
||||
WEBRTC_TRACE_MAX_MESSAGE_SIZE);
|
||||
}
|
||||
_nextFreeIdx[_activeQueue] = WEBRTC_TRACE_MAX_QUEUE/4;
|
||||
} else {
|
||||
// More messages are being written than there is room for in the
|
||||
// buffer. Drop any new messages.
|
||||
// TODO (hellner): its probably better to drop old messages instead
|
||||
// of new ones. One step further: if this happens
|
||||
// it's due to writing faster than what can be
|
||||
// processed. Maybe modify the filter at this point.
|
||||
// E.g. turn of STREAM.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_UWord16 idx = _nextFreeIdx[_activeQueue];
|
||||
_nextFreeIdx[_activeQueue]++;
|
||||
|
||||
_level[_activeQueue][idx] = level;
|
||||
_length[_activeQueue][idx] = length;
|
||||
memcpy(_messageQueue[_activeQueue][idx], traceMessage, length);
|
||||
|
||||
if(_nextFreeIdx[_activeQueue] == WEBRTC_TRACE_MAX_QUEUE-1)
|
||||
{
|
||||
// Loggin more messages than can be worked off. Log a warning.
|
||||
memcpy(_messageQueue[_activeQueue][_nextFreeIdx[_activeQueue]],
|
||||
"WARNING MISSING TRACE MESSAGES\n", 32);
|
||||
_nextFreeIdx[_activeQueue]++;
|
||||
}
|
||||
}
|
||||
|
||||
bool TraceImpl::Run(void* obj)
|
||||
{
|
||||
return static_cast<TraceImpl*>(obj)->Process();
|
||||
}
|
||||
|
||||
bool TraceImpl::Process()
|
||||
{
|
||||
if(_event.Wait(1000) == kEventSignaled)
|
||||
{
|
||||
if(_traceFile.Open() || _callback)
|
||||
{
|
||||
// File mode (not calback mode).
|
||||
WriteToFile();
|
||||
}
|
||||
} else {
|
||||
_traceFile.Flush();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TraceImpl::WriteToFile()
|
||||
{
|
||||
WebRtc_UWord8 localQueueActive = 0;
|
||||
WebRtc_UWord16 localNextFreeIdx = 0;
|
||||
|
||||
// There are two buffer. One for reading (for writing to file) and one for
|
||||
// writing (for storing new messages). Let new messages be posted to the
|
||||
// unused buffer so that the current buffer can be flushed safely.
|
||||
{
|
||||
CriticalSectionScoped lock(_critsectArray);
|
||||
localNextFreeIdx = _nextFreeIdx[_activeQueue];
|
||||
_nextFreeIdx[_activeQueue] = 0;
|
||||
localQueueActive = _activeQueue;
|
||||
if(_activeQueue == 0)
|
||||
{
|
||||
_activeQueue = 1;
|
||||
} else
|
||||
{
|
||||
_activeQueue = 0;
|
||||
}
|
||||
}
|
||||
if(localNextFreeIdx == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CriticalSectionScoped lock(_critsectInterface);
|
||||
|
||||
for(WebRtc_UWord16 idx = 0; idx <localNextFreeIdx; idx++)
|
||||
{
|
||||
TraceLevel localLevel = _level[localQueueActive][idx];
|
||||
if(_callback)
|
||||
{
|
||||
_callback->Print(localLevel, _messageQueue[localQueueActive][idx],
|
||||
_length[localQueueActive][idx]);
|
||||
}
|
||||
if(_traceFile.Open())
|
||||
{
|
||||
if(_rowCountText > WEBRTC_TRACE_MAX_FILE_SIZE)
|
||||
{
|
||||
// wrap file
|
||||
_rowCountText = 0;
|
||||
_traceFile.Flush();
|
||||
|
||||
if(_fileCountText == 0)
|
||||
{
|
||||
_traceFile.Rewind();
|
||||
} else
|
||||
{
|
||||
WebRtc_Word8 oldFileName[FileWrapper::kMaxFileNameSize];
|
||||
WebRtc_Word8 newFileName[FileWrapper::kMaxFileNameSize];
|
||||
|
||||
// get current name
|
||||
_traceFile.FileName(oldFileName,
|
||||
FileWrapper::kMaxFileNameSize);
|
||||
_traceFile.CloseFile();
|
||||
|
||||
_fileCountText++;
|
||||
|
||||
UpdateFileName(oldFileName, newFileName, _fileCountText);
|
||||
|
||||
if(_traceFile.OpenFile(newFileName, false, false,
|
||||
true) == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_rowCountText == 0)
|
||||
{
|
||||
WebRtc_Word8 message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
|
||||
WebRtc_Word32 length = AddDateTimeInfo(message);
|
||||
if(length != -1)
|
||||
{
|
||||
message[length] = 0;
|
||||
message[length-1] = '\n';
|
||||
_traceFile.Write(message, length);
|
||||
_rowCountText++;
|
||||
}
|
||||
length = AddBuildInfo(message);
|
||||
if(length != -1)
|
||||
{
|
||||
message[length+1] = 0;
|
||||
message[length] = '\n';
|
||||
message[length-1] = '\n';
|
||||
_traceFile.Write(message, length+1);
|
||||
_rowCountText++;
|
||||
_rowCountText++;
|
||||
}
|
||||
}
|
||||
WebRtc_UWord16 length = _length[localQueueActive][idx];
|
||||
_messageQueue[localQueueActive][idx][length] = 0;
|
||||
_messageQueue[localQueueActive][idx][length-1] = '\n';
|
||||
_traceFile.Write(_messageQueue[localQueueActive][idx], length);
|
||||
_rowCountText++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TraceImpl::AddImpl(const TraceLevel level, const TraceModule module,
|
||||
const WebRtc_Word32 id,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE])
|
||||
{
|
||||
if (TraceCheck(level))
|
||||
{
|
||||
char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* meassagePtr = traceMessage;
|
||||
|
||||
WebRtc_Word32 len = 0;
|
||||
WebRtc_Word32 ackLen = 0;
|
||||
|
||||
len = AddLevel(meassagePtr, level);
|
||||
if(len == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
meassagePtr += len;
|
||||
ackLen += len;
|
||||
|
||||
len = AddTime(meassagePtr, level);
|
||||
if(len == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
meassagePtr += len;
|
||||
ackLen += len;
|
||||
|
||||
len = AddModuleAndId(meassagePtr, module, id);
|
||||
if(len == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
meassagePtr += len;
|
||||
ackLen += len;
|
||||
|
||||
len = AddThreadId(meassagePtr);
|
||||
if(len == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
meassagePtr += len;
|
||||
ackLen += len;
|
||||
|
||||
len = AddMessage(meassagePtr, msg, (WebRtc_UWord16)ackLen);
|
||||
if(len == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ackLen += len;
|
||||
AddMessageToList(traceMessage,(WebRtc_UWord16)ackLen, level);
|
||||
|
||||
// Make sure that messages are written as soon as possible.
|
||||
_event.Set();
|
||||
}
|
||||
}
|
||||
|
||||
bool TraceImpl::TraceCheck(const TraceLevel level) const
|
||||
{
|
||||
return (level & levelFilter)? true:false;
|
||||
}
|
||||
|
||||
bool TraceImpl::UpdateFileName(
|
||||
const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
|
||||
WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
|
||||
const WebRtc_UWord32 newCount) const
|
||||
{
|
||||
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
|
||||
if(length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WebRtc_Word32 lengthWithoutFileEnding = length-1;
|
||||
while(lengthWithoutFileEnding > 0)
|
||||
{
|
||||
if(fileNameUTF8[lengthWithoutFileEnding] == '.')
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
lengthWithoutFileEnding--;
|
||||
}
|
||||
}
|
||||
if(lengthWithoutFileEnding == 0)
|
||||
{
|
||||
lengthWithoutFileEnding = length;
|
||||
}
|
||||
WebRtc_Word32 lengthTo_ = lengthWithoutFileEnding - 1;
|
||||
while(lengthTo_ > 0)
|
||||
{
|
||||
if(fileNameUTF8[lengthTo_] == '_')
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
lengthTo_--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(fileNameWithCounterUTF8, fileNameUTF8, lengthTo_);
|
||||
sprintf(fileNameWithCounterUTF8+lengthTo_, "_%lu%s", newCount,
|
||||
fileNameUTF8+lengthWithoutFileEnding);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceImpl::CreateFileName(
|
||||
const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
|
||||
WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
|
||||
const WebRtc_UWord32 newCount) const
|
||||
{
|
||||
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
|
||||
if(length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WebRtc_Word32 lengthWithoutFileEnding = length-1;
|
||||
while(lengthWithoutFileEnding > 0)
|
||||
{
|
||||
if(fileNameUTF8[lengthWithoutFileEnding] == '.')
|
||||
{
|
||||
break;
|
||||
}else
|
||||
{
|
||||
lengthWithoutFileEnding--;
|
||||
}
|
||||
}
|
||||
if(lengthWithoutFileEnding == 0)
|
||||
{
|
||||
lengthWithoutFileEnding = length;
|
||||
}
|
||||
memcpy(fileNameWithCounterUTF8, fileNameUTF8, lengthWithoutFileEnding);
|
||||
sprintf(fileNameWithCounterUTF8+lengthWithoutFileEnding, "_%lu%s",
|
||||
newCount, fileNameUTF8+lengthWithoutFileEnding);
|
||||
return true;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter)
|
||||
{
|
||||
levelFilter = filter;
|
||||
return 0;
|
||||
};
|
||||
|
||||
WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter)
|
||||
{
|
||||
filter = levelFilter;
|
||||
return 0;
|
||||
};
|
||||
|
||||
WebRtc_Word32 Trace::TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize])
|
||||
{
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if(trace)
|
||||
{
|
||||
int retVal = trace->TraceFileImpl(fileName);
|
||||
ReturnTrace();
|
||||
return retVal;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* fileName,
|
||||
const bool addFileCounter)
|
||||
{
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if(trace)
|
||||
{
|
||||
int retVal = trace->SetTraceFileImpl(fileName, addFileCounter);
|
||||
ReturnTrace();
|
||||
return retVal;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 Trace::SetTraceCallback(TraceCallback* callback)
|
||||
{
|
||||
TraceImpl* trace = TraceImpl::GetTrace();
|
||||
if(trace)
|
||||
{
|
||||
int retVal = trace->SetTraceCallbackImpl(callback);
|
||||
ReturnTrace();
|
||||
return retVal;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Trace::Add(const TraceLevel level, const TraceModule module,
|
||||
const WebRtc_Word32 id, const char* msg, ...)
|
||||
|
||||
{
|
||||
TraceImpl* trace = TraceImpl::GetTrace(level);
|
||||
if(trace)
|
||||
{
|
||||
if(trace->TraceCheck(level))
|
||||
{
|
||||
char tempBuff[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
|
||||
char* buff = 0;
|
||||
if(msg)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
#ifdef _WIN32
|
||||
_vsnprintf(tempBuff,WEBRTC_TRACE_MAX_MESSAGE_SIZE-1,msg,args);
|
||||
#else
|
||||
vsnprintf(tempBuff,WEBRTC_TRACE_MAX_MESSAGE_SIZE-1,msg,args);
|
||||
#endif
|
||||
va_end(args);
|
||||
buff = tempBuff;
|
||||
}
|
||||
trace->AddImpl(level, module, id, buff);
|
||||
}
|
||||
ReturnTrace();
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
141
system_wrappers/source/trace_impl.h
Normal file
141
system_wrappers/source/trace_impl.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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_IMPL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
||||
|
||||
#include "system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "system_wrappers/interface/event_wrapper.h"
|
||||
#include "system_wrappers/interface/file_wrapper.h"
|
||||
#include "system_wrappers/interface/trace.h"
|
||||
#include "system_wrappers/interface/thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
enum TraceCount
|
||||
{
|
||||
WEBRTC_TRACE_DEC = 0,
|
||||
WEBRTC_TRACE_INC = 1,
|
||||
WEBRTC_TRACE_INC_NO_CREATE = 2
|
||||
};
|
||||
|
||||
enum TraceCreate
|
||||
{
|
||||
WEBRTC_TRACE_EXIST = 0,
|
||||
WEBRTC_TRACE_CREATE = 1,
|
||||
WEBRTC_TRACE_DESTROY = 2
|
||||
};
|
||||
|
||||
// TODO (pwestin) WEBRTC_TRACE_MAX_QUEUE needs to be tweaked
|
||||
// TODO (hellner) the buffer should be close to how much the system can write to
|
||||
// file. Increasing the buffer will not solve anything. Sooner or
|
||||
// later the buffer is going to fill up anyways.
|
||||
#if defined(MAC_IPHONE)
|
||||
#define WEBRTC_TRACE_MAX_QUEUE 2000
|
||||
#else
|
||||
#define WEBRTC_TRACE_MAX_QUEUE 8000
|
||||
#endif
|
||||
#define WEBRTC_TRACE_NUM_ARRAY 2
|
||||
#define WEBRTC_TRACE_MAX_MESSAGE_SIZE 256
|
||||
// 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 Trace* CreateTrace();
|
||||
static TraceImpl* GetTrace(const TraceLevel level = kTraceAll);
|
||||
|
||||
static Trace* StaticInstance(TraceCount inc,
|
||||
const TraceLevel level = kTraceAll);
|
||||
|
||||
WebRtc_Word32 SetTraceFileImpl(const WebRtc_Word8* fileName,
|
||||
const bool addFileCounter);
|
||||
WebRtc_Word32 TraceFileImpl(
|
||||
WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize]);
|
||||
|
||||
WebRtc_Word32 SetTraceCallbackImpl(TraceCallback* callback);
|
||||
|
||||
void AddImpl(const TraceLevel level, const TraceModule module,
|
||||
const WebRtc_Word32 id, const char* msg);
|
||||
|
||||
bool StopThread();
|
||||
|
||||
bool TraceCheck(const TraceLevel level) const;
|
||||
|
||||
protected:
|
||||
TraceImpl();
|
||||
|
||||
// OS specific implementations
|
||||
virtual WebRtc_Word32 AddThreadId(char* traceMessage) const = 0;
|
||||
virtual WebRtc_Word32 AddTime(char* traceMessage,
|
||||
const TraceLevel level) const = 0;
|
||||
|
||||
virtual WebRtc_Word32 AddBuildInfo(char* traceMessage) const = 0;
|
||||
virtual WebRtc_Word32 AddDateTimeInfo(char* traceMessage) const = 0;
|
||||
|
||||
static bool Run(void* obj);
|
||||
bool Process();
|
||||
|
||||
private:
|
||||
WebRtc_Word32 AddLevel(char* szMessage, const TraceLevel level) const;
|
||||
|
||||
WebRtc_Word32 AddModuleAndId(char* traceMessage, const TraceModule module,
|
||||
const WebRtc_Word32 id) const;
|
||||
|
||||
WebRtc_Word32 AddMessage(char* traceMessage,
|
||||
const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const WebRtc_UWord16 writtenSoFar) const;
|
||||
|
||||
void AddMessageToList(
|
||||
const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
|
||||
const WebRtc_UWord16 length,
|
||||
const TraceLevel level);
|
||||
|
||||
bool UpdateFileName(
|
||||
const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
|
||||
WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
|
||||
const WebRtc_UWord32 newCount) const;
|
||||
|
||||
bool CreateFileName(
|
||||
const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
|
||||
WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
|
||||
const WebRtc_UWord32 newCount) const;
|
||||
|
||||
void WriteToFile();
|
||||
|
||||
CriticalSectionWrapper& _critsectInterface;
|
||||
TraceCallback* _callback;
|
||||
WebRtc_UWord32 _rowCountText;
|
||||
WebRtc_UWord32 _fileCountText;
|
||||
|
||||
FileWrapper& _traceFile;
|
||||
ThreadWrapper& _thread;
|
||||
EventWrapper& _event;
|
||||
|
||||
// _critsectArray protects _activeQueue
|
||||
CriticalSectionWrapper& _critsectArray;
|
||||
WebRtc_UWord16 _nextFreeIdx[WEBRTC_TRACE_NUM_ARRAY];
|
||||
TraceLevel _level[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
|
||||
WebRtc_UWord16 _length[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
|
||||
WebRtc_Word8* _messageQueue[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
|
||||
WebRtc_UWord8 _activeQueue;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_IMPL_H_
|
133
system_wrappers/source/trace_linux.cc
Normal file
133
system_wrappers/source/trace_linux.cc
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 "trace_linux.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#define BUILDMODE "d"
|
||||
#elif defined(DEBUG)
|
||||
#define BUILDMODE "d"
|
||||
#elif defined(NDEBUG)
|
||||
#define BUILDMODE "r"
|
||||
#else
|
||||
#define BUILDMODE "?"
|
||||
#endif
|
||||
#define BUILDTIME __TIME__
|
||||
#define BUILDDATE __DATE__
|
||||
// example: "Oct 10 2002 12:05:30 r"
|
||||
#define BUILDINFO BUILDDATE " " BUILDTIME " " BUILDMODE
|
||||
|
||||
namespace webrtc {
|
||||
TraceLinux::TraceLinux()
|
||||
{
|
||||
_prevAPITickCount = time(NULL);
|
||||
_prevTickCount = _prevAPITickCount;
|
||||
}
|
||||
|
||||
TraceLinux::~TraceLinux()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceLinux::AddThreadId(char* traceMessage) const
|
||||
{
|
||||
WebRtc_UWord64 threadId = (WebRtc_UWord64)pthread_self();
|
||||
sprintf(traceMessage, "%10llu; ", threadId);
|
||||
// 12 bytes are written.
|
||||
return 12;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceLinux::AddTime(char* traceMessage,
|
||||
const TraceLevel level) const
|
||||
{
|
||||
time_t dwCurrentTimeInSeconds = time(NULL);
|
||||
struct tm systemTime;
|
||||
gmtime_r(&dwCurrentTimeInSeconds, &systemTime);
|
||||
|
||||
if(level == kTraceApiCall)
|
||||
{
|
||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevTickCount;
|
||||
_prevTickCount = dwCurrentTimeInSeconds;
|
||||
|
||||
if(_prevTickCount == 0)
|
||||
{
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 0x0fffffff)
|
||||
{
|
||||
// Either wraparound or data race.
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 99999)
|
||||
{
|
||||
dwDeltaTime = 99999;
|
||||
}
|
||||
|
||||
sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
|
||||
systemTime.tm_min, systemTime.tm_sec, 0, dwDeltaTime);
|
||||
} else {
|
||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevAPITickCount;
|
||||
_prevAPITickCount = dwCurrentTimeInSeconds;
|
||||
if(_prevAPITickCount == 0)
|
||||
{
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 0x0fffffff)
|
||||
{
|
||||
// Either wraparound or data race.
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 99999)
|
||||
{
|
||||
dwDeltaTime = 99999;
|
||||
}
|
||||
sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
|
||||
systemTime.tm_min, systemTime.tm_sec, 0, dwDeltaTime);
|
||||
}
|
||||
// Messages is 22 characters.
|
||||
return 22;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceLinux::AddBuildInfo(char* traceMessage) const
|
||||
{
|
||||
sprintf(traceMessage, "Build info: %s", BUILDINFO);
|
||||
// Include NULL termination (hence + 1).
|
||||
return strlen(traceMessage) + 1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceLinux::AddDateTimeInfo(char* traceMessage) const
|
||||
{
|
||||
time_t t;
|
||||
time(&t);
|
||||
sprintf(traceMessage, "Local Date: %s", ctime(&t));
|
||||
WebRtc_Word32 len = static_cast<WebRtc_Word32>(strlen(traceMessage));
|
||||
|
||||
if ('\n' == traceMessage[len - 1])
|
||||
{
|
||||
traceMessage[len - 1] = '\0';
|
||||
--len;
|
||||
}
|
||||
|
||||
// Messages is 12 characters.
|
||||
return len + 1;
|
||||
}
|
||||
} // namespace webrtc
|
37
system_wrappers/source/trace_linux.h
Normal file
37
system_wrappers/source/trace_linux.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_LINUX_H_
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "trace_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
class TraceLinux : public TraceImpl
|
||||
{
|
||||
public:
|
||||
TraceLinux();
|
||||
virtual ~TraceLinux();
|
||||
|
||||
virtual WebRtc_Word32 AddThreadId(char *traceMessage) const;
|
||||
virtual WebRtc_Word32 AddTime(char* traceMessage,
|
||||
const TraceLevel level) const;
|
||||
|
||||
virtual WebRtc_Word32 AddBuildInfo(char* traceMessage) const;
|
||||
virtual WebRtc_Word32 AddDateTimeInfo(char* traceMessage) const;
|
||||
|
||||
private:
|
||||
volatile mutable WebRtc_UWord32 _prevAPITickCount;
|
||||
volatile mutable WebRtc_UWord32 _prevTickCount;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_LINUX_H_
|
141
system_wrappers/source/trace_windows.cc
Normal file
141
system_wrappers/source/trace_windows.cc
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 "trace_windows.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Mmsystem.h"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#define BUILDMODE "d"
|
||||
#elif defined(DEBUG)
|
||||
#define BUILDMODE "d"
|
||||
#elif defined(NDEBUG)
|
||||
#define BUILDMODE "r"
|
||||
#else
|
||||
#define BUILDMODE "?"
|
||||
#endif
|
||||
#define BUILDTIME __TIME__
|
||||
#define BUILDDATE __DATE__
|
||||
// Example: "Oct 10 2002 12:05:30 r"
|
||||
#define BUILDINFO BUILDDATE " " BUILDTIME " " BUILDMODE
|
||||
|
||||
namespace webrtc {
|
||||
TraceWindows::TraceWindows()
|
||||
: _prevAPITickCount(0),
|
||||
_prevTickCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
TraceWindows::~TraceWindows()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceWindows::AddThreadId(char* traceMessage) const
|
||||
{
|
||||
WebRtc_UWord32 threadId= GetCurrentThreadId();
|
||||
sprintf (traceMessage, "%10u; ", threadId);
|
||||
// Messages is 12 characters.
|
||||
return 12;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceWindows::AddTime(char* traceMessage,
|
||||
const TraceLevel level) const
|
||||
{
|
||||
WebRtc_UWord32 dwCurrentTime = timeGetTime();
|
||||
SYSTEMTIME systemTime;
|
||||
GetSystemTime(&systemTime);
|
||||
|
||||
if(level == kTraceApiCall)
|
||||
{
|
||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTime- _prevTickCount;
|
||||
_prevTickCount = dwCurrentTime;
|
||||
|
||||
if(_prevTickCount == 0)
|
||||
{
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 0x0fffffff)
|
||||
{
|
||||
// Either wraparound or data race.
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 99999)
|
||||
{
|
||||
dwDeltaTime = 99999;
|
||||
}
|
||||
|
||||
sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
|
||||
systemTime.wMinute, systemTime.wSecond,
|
||||
systemTime.wMilliseconds, dwDeltaTime);
|
||||
} else {
|
||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTime - _prevAPITickCount;
|
||||
_prevAPITickCount = dwCurrentTime;
|
||||
|
||||
if(_prevAPITickCount == 0)
|
||||
{
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 0x0fffffff)
|
||||
{
|
||||
// Either wraparound or data race.
|
||||
dwDeltaTime = 0;
|
||||
}
|
||||
if(dwDeltaTime > 99999)
|
||||
{
|
||||
dwDeltaTime = 99999;
|
||||
}
|
||||
sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
|
||||
systemTime.wMinute, systemTime.wSecond,
|
||||
systemTime.wMilliseconds, dwDeltaTime);
|
||||
}
|
||||
// Messages is 12 characters.
|
||||
return 22;
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceWindows::AddBuildInfo(char* traceMessage) const
|
||||
{
|
||||
// write data and time to text file
|
||||
sprintf(traceMessage, "Build info: %s", BUILDINFO);
|
||||
// Include NULL termination (hence + 1).
|
||||
return static_cast<WebRtc_Word32>(strlen(traceMessage)+1);
|
||||
}
|
||||
|
||||
WebRtc_Word32 TraceWindows::AddDateTimeInfo(char* traceMessage) const
|
||||
{
|
||||
_prevAPITickCount = timeGetTime();
|
||||
_prevTickCount = _prevAPITickCount;
|
||||
|
||||
SYSTEMTIME sysTime;
|
||||
GetLocalTime (&sysTime);
|
||||
|
||||
TCHAR szDateStr[20];
|
||||
TCHAR szTimeStr[20];
|
||||
TCHAR *pSzDateStr = szDateStr;
|
||||
TCHAR *pSzTimeStr = szTimeStr;
|
||||
|
||||
// Create date string (e.g. Apr 04 2002)
|
||||
GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("MMM dd yyyy"),
|
||||
szDateStr, 20);
|
||||
|
||||
// Create time string (e.g. 15:32:08)
|
||||
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("HH':'mm':'ss"),
|
||||
szTimeStr, 20);
|
||||
|
||||
sprintf(traceMessage, "Local Date: %s Local Time: %s", szDateStr,
|
||||
szTimeStr);
|
||||
|
||||
// Include NULL termination (hence + 1).
|
||||
return static_cast<WebRtc_Word32>(strlen(traceMessage)+ 1);
|
||||
}
|
||||
} // namespace webrtc
|
37
system_wrappers/source/trace_windows.h
Normal file
37
system_wrappers/source/trace_windows.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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_WINDOWS_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
|
||||
|
||||
#include "trace_impl.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
namespace webrtc {
|
||||
class TraceWindows : public TraceImpl
|
||||
{
|
||||
public:
|
||||
TraceWindows();
|
||||
virtual ~TraceWindows();
|
||||
|
||||
virtual WebRtc_Word32 AddThreadId(char *traceMessage) const;
|
||||
virtual WebRtc_Word32 AddTime(char* traceMessage,
|
||||
const TraceLevel level) const;
|
||||
|
||||
virtual WebRtc_Word32 AddBuildInfo(char* traceMessage) const;
|
||||
virtual WebRtc_Word32 AddDateTimeInfo(char* traceMessage) const;
|
||||
private:
|
||||
volatile mutable WebRtc_UWord32 _prevAPITickCount;
|
||||
volatile mutable WebRtc_UWord32 _prevTickCount;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
|
65
system_wrappers/test/Test.cpp
Normal file
65
system_wrappers/test/Test.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define Sleep(x) usleep(x*1000)
|
||||
#endif
|
||||
|
||||
#include "common_types.h"
|
||||
#include "trace.h"
|
||||
#include "cpu_wrapper.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
#else
|
||||
int main(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
Trace::CreateTrace();
|
||||
Trace::SetTraceFile("testTrace.txt");
|
||||
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||||
|
||||
printf("Start system wrapper test\n");
|
||||
|
||||
printf("Number of cores detected:%u\n", (unsigned int)CpuWrapper::DetectNumberOfCores());
|
||||
|
||||
CpuWrapper* cpu = CpuWrapper::CreateCpu();
|
||||
|
||||
WebRtc_UWord32 numCores;
|
||||
WebRtc_UWord32* cores;
|
||||
|
||||
for(int i = 0; i< 10;i++)
|
||||
{
|
||||
WebRtc_Word32 total = cpu->CpuUsageMultiCore(numCores, cores);
|
||||
|
||||
printf("\nNumCores:%d\n", (int)numCores);
|
||||
printf("Total cpu:%d\n", (int)total);
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i< numCores;i++)
|
||||
{
|
||||
printf("Core:%lu CPU:%lu \n", i, cores[i]);
|
||||
}
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
printf("Done system wrapper test\n");
|
||||
|
||||
delete cpu;
|
||||
|
||||
Trace::ReturnTrace();
|
||||
};
|
265
system_wrappers/test/TestSort/TestSort.cpp
Normal file
265
system_wrappers/test/TestSort/TestSort.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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 <cstdio>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "sort.h"
|
||||
#include "tick_util.h"
|
||||
|
||||
// Excellent work polluting the global namespace Visual Studio...
|
||||
#undef max
|
||||
#undef min
|
||||
#include <limits>
|
||||
|
||||
template<typename KeyType>
|
||||
struct LotsOfData
|
||||
{
|
||||
KeyType key;
|
||||
char data[64];
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
int Compare(const void* dataX, const void* dataY)
|
||||
{
|
||||
DataType dataX = (DataType)*(const DataType*)dataX;
|
||||
DataType dataY = (DataType)*(const DataType*)dataY;
|
||||
if (dataX > dataY)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (dataX < dataY)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
template<typename DataType, typename KeyType>
|
||||
int CompareKey(const void* dataX, const void* dataY)
|
||||
{
|
||||
KeyType keyX = ((const DataType*)dataX)->key;
|
||||
KeyType keyY = ((const DataType*)dataY)->key;
|
||||
if (keyX > keyY)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (keyX < keyY)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
struct KeyLessThan
|
||||
{
|
||||
bool operator()(const DataType &dataX, const DataType &dataY) const
|
||||
{
|
||||
return dataX.key < dataY.key;
|
||||
}
|
||||
};
|
||||
|
||||
const char* TypeEnumToString(webrtc::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
using namespace webrtc;
|
||||
case TYPE_Word8:
|
||||
return "Word8";
|
||||
case TYPE_UWord8:
|
||||
return "UWord8";
|
||||
case TYPE_Word16:
|
||||
return "Word16";
|
||||
case TYPE_UWord16:
|
||||
return "UWord16";
|
||||
case TYPE_Word32:
|
||||
return "Word32";
|
||||
case TYPE_UWord32:
|
||||
return "UWord32";
|
||||
case TYPE_Word64:
|
||||
return "Word64";
|
||||
case TYPE_UWord64:
|
||||
return "UWord64";
|
||||
case TYPE_Float32:
|
||||
return "Float32";
|
||||
case TYPE_Float64:
|
||||
return "Float64";
|
||||
default:
|
||||
return "Unrecognized";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
Type TypedRand()
|
||||
{
|
||||
if (std::numeric_limits<Type>::is_integer)
|
||||
{
|
||||
double floatRand = static_cast<double>(rand()) / RAND_MAX;
|
||||
if (std::numeric_limits<Type>::is_signed)
|
||||
{
|
||||
floatRand -= 0.5;
|
||||
}
|
||||
|
||||
// Uniform [-max()/2, max()/2] for signed
|
||||
// [0, max()] for unsigned
|
||||
return static_cast<Type>(floatRand * std::numeric_limits<Type>::max());
|
||||
}
|
||||
else // Floating point
|
||||
{
|
||||
// Uniform [-0.5, 0.5]
|
||||
// The outer cast is to remove template warnings.
|
||||
return static_cast<Type>((static_cast<Type>(rand()) / RAND_MAX) - 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename KeyType>
|
||||
void RunSortTest(webrtc::Type sortType, bool keySort)
|
||||
{
|
||||
enum { DataLength = 1000 };
|
||||
enum { NumOfTests = 10000 };
|
||||
KeyType key[DataLength];
|
||||
KeyType keyRef[DataLength];
|
||||
LotsOfData<KeyType> data[DataLength];
|
||||
LotsOfData<KeyType> dataRef[DataLength];
|
||||
WebRtc_Word32 retVal = 0;
|
||||
|
||||
if (keySort)
|
||||
{
|
||||
printf("Running %s KeySort() tests...\n", TypeEnumToString(sortType));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Running %s Sort() tests...\n", TypeEnumToString(sortType));
|
||||
}
|
||||
|
||||
TickInterval accTicks;
|
||||
for (int i = 0; i < NumOfTests; i++)
|
||||
{
|
||||
for (int j = 0; j < DataLength; j++)
|
||||
{
|
||||
key[j] = TypedRand<KeyType>();
|
||||
data[j].key = key[j];
|
||||
// Write index to payload. We use this later for verification.
|
||||
sprintf(data[j].data, "%d", j);
|
||||
}
|
||||
|
||||
memcpy(dataRef, data, sizeof(data));
|
||||
memcpy(keyRef, key, sizeof(key));
|
||||
|
||||
retVal = 0;
|
||||
TickTime t0 = TickTime::Now();
|
||||
if (keySort)
|
||||
{
|
||||
retVal = webrtc::KeySort(data, key, DataLength, sizeof(LotsOfData<KeyType>),
|
||||
sortType);
|
||||
|
||||
//std::sort(data, data + DataLength, KeyLessThan<KeyType>());
|
||||
//qsort(data, DataLength, sizeof(LotsOfData<KeyType>),
|
||||
// CompareKey<LotsOfData<KeyType>, KeyType>);
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = webrtc::Sort(key, DataLength, sortType);
|
||||
|
||||
//std::sort(key, key + DataLength);
|
||||
//qsort(key, DataLength, sizeof(KeyType), Compare<KeyType>);
|
||||
}
|
||||
TickTime t1 = TickTime::Now();
|
||||
accTicks += (t1 - t0);
|
||||
|
||||
if (retVal != 0)
|
||||
{
|
||||
printf("Test failed at iteration %d:\n", i);
|
||||
printf("Sort returned an error. ");
|
||||
printf("It likely does not support the requested type\nExiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Reference sort.
|
||||
if (!keySort)
|
||||
{
|
||||
std::sort(keyRef, keyRef + DataLength);
|
||||
}
|
||||
|
||||
if (keySort)
|
||||
{
|
||||
for (int j = 0; j < DataLength - 1; j++)
|
||||
{
|
||||
if (data[j].key > data[j + 1].key)
|
||||
{
|
||||
printf("Test failed at iteration %d:\n", i);
|
||||
printf("Keys are not monotonically increasing\nExiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int index = atoi(data[j].data);
|
||||
if (index < 0 || index >= DataLength || data[j].key != dataRef[index].key)
|
||||
{
|
||||
printf("Test failed at iteration %d:\n", i);
|
||||
printf("Payload data is corrupt\nExiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < DataLength - 1; j++)
|
||||
{
|
||||
if (key[j] > key[j + 1])
|
||||
{
|
||||
printf("Test failed at iteration %d:\n", i);
|
||||
printf("Data is not monotonically increasing\nExiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(key, keyRef, sizeof(key)) != 0)
|
||||
{
|
||||
printf("Test failed at iteration %d:\n", i);
|
||||
printf("Sort data differs from std::sort reference\nExiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Compliance test passed over %d iterations\n", NumOfTests);
|
||||
|
||||
WebRtc_Word64 executeTime = accTicks.Milliseconds();
|
||||
printf("Execute time: %.2f s\n\n", (float)executeTime / 1000);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Seed rand().
|
||||
srand(42);
|
||||
bool keySort = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
RunSortTest<WebRtc_Word8>(webrtc::TYPE_Word8, keySort);
|
||||
RunSortTest<WebRtc_UWord8>(webrtc::TYPE_UWord8, keySort);
|
||||
RunSortTest<WebRtc_Word16>(webrtc::TYPE_Word16, keySort);
|
||||
RunSortTest<WebRtc_UWord16>(webrtc::TYPE_UWord16, keySort);
|
||||
RunSortTest<WebRtc_Word32>(webrtc::TYPE_Word32, keySort);
|
||||
RunSortTest<WebRtc_UWord32>(webrtc::TYPE_UWord32, keySort);
|
||||
RunSortTest<WebRtc_Word64>(webrtc::TYPE_Word64, keySort);
|
||||
RunSortTest<WebRtc_UWord64>(webrtc::TYPE_UWord64, keySort);
|
||||
RunSortTest<float>(webrtc::TYPE_Float32, keySort);
|
||||
RunSortTest<double>(webrtc::TYPE_Float64, keySort);
|
||||
|
||||
keySort = !keySort;
|
||||
}
|
||||
|
||||
printf("All tests passed\n");
|
||||
|
||||
return 0;
|
||||
}
|
174
system_wrappers/test/list/list.cc
Normal file
174
system_wrappers/test/list/list.cc
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "list_wrapper.h"
|
||||
|
||||
const int kNumberOfElements = 10;
|
||||
|
||||
void FailTest(bool failed)
|
||||
{
|
||||
if (failed)
|
||||
{
|
||||
printf("Test failed!\n");
|
||||
printf("Press enter to continue:");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int GetStoredIntegerValue(ListItem* list_item)
|
||||
{
|
||||
void* list_item_pointer = list_item->GetItem();
|
||||
if (list_item_pointer != NULL)
|
||||
{
|
||||
return *(reinterpret_cast<int*>(list_item_pointer));
|
||||
}
|
||||
return static_cast<int>(list_item->GetUnsignedItem());
|
||||
}
|
||||
|
||||
void PrintList(ListWrapper& list)
|
||||
{
|
||||
ListItem* list_item = list.First();
|
||||
printf("List: ");
|
||||
while (list_item != NULL)
|
||||
{
|
||||
int item_value = GetStoredIntegerValue(list_item);
|
||||
FailTest(item_value < 0);
|
||||
printf(" %d",item_value);
|
||||
list_item = list.Next(list_item);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// The list should always be in ascending order
|
||||
void ListSanity(ListWrapper& list)
|
||||
{
|
||||
if(list.Empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ListItem* item_iter = list.First();
|
||||
// Fake a previous value for the first iteration
|
||||
int previous_value = GetStoredIntegerValue(item_iter) - 1;
|
||||
while (item_iter != NULL)
|
||||
{
|
||||
const int value = GetStoredIntegerValue(item_iter);
|
||||
FailTest(value != previous_value + 1);
|
||||
previous_value = value;
|
||||
item_iter = list.Next(item_iter);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char* /*argv*/[])
|
||||
{
|
||||
printf("List Test:\n");
|
||||
int element_array[kNumberOfElements];
|
||||
for (int i = 0; i < kNumberOfElements; i++)
|
||||
{
|
||||
element_array[i] = i;
|
||||
}
|
||||
// Test PushBack 1
|
||||
ListWrapper test_list;
|
||||
for (int i = 2; i < kNumberOfElements - 2; i++)
|
||||
{
|
||||
FailTest(test_list.PushBack((void*)&element_array[i]) != 0);
|
||||
}
|
||||
// Test PushBack 2
|
||||
FailTest(test_list.PushBack(element_array[kNumberOfElements - 2]) != 0);
|
||||
FailTest(test_list.PushBack(element_array[kNumberOfElements - 1]) != 0);
|
||||
// Test PushFront 2
|
||||
FailTest(test_list.PushFront(element_array[1]) != 0);
|
||||
// Test PushFront 1
|
||||
FailTest(test_list.PushFront((void*)&element_array[0]) != 0);
|
||||
// Test GetSize
|
||||
FailTest(test_list.GetSize() != kNumberOfElements);
|
||||
PrintList(test_list);
|
||||
//Test PopFront
|
||||
FailTest(test_list.PopFront() != 0);
|
||||
//Test PopBack
|
||||
FailTest(test_list.PopBack() != 0);
|
||||
// Test GetSize
|
||||
FailTest(test_list.GetSize() != kNumberOfElements - 2);
|
||||
// Test Empty
|
||||
FailTest(test_list.Empty());
|
||||
// Test First
|
||||
ListItem* first_item = test_list.First();
|
||||
FailTest(first_item == NULL);
|
||||
// Test Last
|
||||
ListItem* last_item = test_list.Last();
|
||||
FailTest(last_item == NULL);
|
||||
// Test Next
|
||||
ListItem* second_item = test_list.Next(first_item);
|
||||
FailTest(second_item == NULL);
|
||||
FailTest(test_list.Next(last_item) != NULL);
|
||||
FailTest(test_list.Next(NULL) != NULL);
|
||||
// Test Previous
|
||||
ListItem* second_to_last_item = test_list.Previous(last_item);
|
||||
FailTest(second_to_last_item == NULL);
|
||||
FailTest(test_list.Previous(first_item) != NULL);
|
||||
FailTest(test_list.Previous(NULL) != NULL);
|
||||
// Test GetUnsignedItem
|
||||
FailTest(last_item->GetUnsignedItem() !=
|
||||
kNumberOfElements - 2);
|
||||
FailTest(last_item->GetItem() !=
|
||||
NULL);
|
||||
// Test GetItem
|
||||
FailTest(GetStoredIntegerValue(second_to_last_item) !=
|
||||
kNumberOfElements - 3);
|
||||
FailTest(second_to_last_item->GetUnsignedItem() != 0);
|
||||
// Pop last and first since they are pushed as unsigned items.
|
||||
FailTest(test_list.PopFront() != 0);
|
||||
FailTest(test_list.PopBack() != 0);
|
||||
// Test Insert. Please note that old iterators are no longer valid at
|
||||
// this point.
|
||||
ListItem* insert_item_last = new ListItem(reinterpret_cast<void*>(&element_array[kNumberOfElements - 2]));
|
||||
FailTest(test_list.Insert(test_list.Last(),insert_item_last) != 0);
|
||||
FailTest(test_list.Insert(NULL,insert_item_last) == 0);
|
||||
ListItem* insert_item_last2 = new ListItem(reinterpret_cast<void*>(&element_array[kNumberOfElements - 2]));
|
||||
FailTest(test_list.Insert(insert_item_last2,NULL) == 0);
|
||||
// test InsertBefore
|
||||
ListItem* insert_item_first = new ListItem(reinterpret_cast<void*>(&element_array[1]));
|
||||
FailTest(test_list.InsertBefore(test_list.First(),insert_item_first) != 0);
|
||||
FailTest(test_list.InsertBefore(NULL,insert_item_first) == 0);
|
||||
ListItem* insert_item_first2 = new ListItem(reinterpret_cast<void*>(&element_array[1]));
|
||||
FailTest(test_list.InsertBefore(insert_item_first2,NULL) == 0);
|
||||
PrintList(test_list);
|
||||
ListSanity(test_list);
|
||||
// Erase the whole list
|
||||
int counter = 0;
|
||||
while (test_list.PopFront() == 0)
|
||||
{
|
||||
FailTest(counter++ > kNumberOfElements);
|
||||
}
|
||||
PrintList(test_list);
|
||||
// Test APIs when list is empty
|
||||
FailTest(test_list.GetSize() != 0);
|
||||
FailTest(test_list.PopFront() != -1);
|
||||
FailTest(test_list.PopBack() != -1);
|
||||
FailTest(!test_list.Empty());
|
||||
FailTest(test_list.First() != NULL);
|
||||
FailTest(test_list.Last() != NULL);
|
||||
FailTest(test_list.Next(NULL) != NULL);
|
||||
FailTest(test_list.Previous(NULL) != NULL);
|
||||
FailTest(test_list.Erase(NULL) != -1);
|
||||
// Test Insert APIs when list is empty
|
||||
ListItem* new_item = new ListItem(reinterpret_cast<void*>(&element_array[0]));
|
||||
FailTest(test_list.Insert(NULL,new_item) != 0);
|
||||
FailTest(test_list.Empty());
|
||||
FailTest(test_list.PopFront() != 0);
|
||||
ListItem* new_item2 = new ListItem(reinterpret_cast<void*>(&element_array[0]));
|
||||
FailTest(test_list.InsertBefore(NULL,new_item2) != 0);
|
||||
FailTest(test_list.Empty());
|
||||
|
||||
printf("Tests passed successfully!\n");
|
||||
}
|
112
system_wrappers/test/map/map.cc
Normal file
112
system_wrappers/test/map/map.cc
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "map_wrapper.h"
|
||||
|
||||
const int kNumberOfElements = 10;
|
||||
|
||||
void FailTest(bool failed)
|
||||
{
|
||||
if (failed)
|
||||
{
|
||||
printf("Test failed!\n");
|
||||
printf("Press enter to continue:");
|
||||
getchar();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int GetStoredIntegerValue(MapItem* map_item)
|
||||
{
|
||||
void* map_item_pointer = map_item->GetItem();
|
||||
if (map_item_pointer != NULL)
|
||||
{
|
||||
return *(reinterpret_cast<int*>(map_item_pointer));
|
||||
}
|
||||
return static_cast<int>(map_item->GetUnsignedId());
|
||||
}
|
||||
|
||||
void PrintMap(MapWrapper& map)
|
||||
{
|
||||
MapItem* map_item = map.First();
|
||||
printf("Map: ");
|
||||
while (map_item != NULL)
|
||||
{
|
||||
int item_value = GetStoredIntegerValue(map_item);
|
||||
FailTest(item_value < 0);
|
||||
printf(" %d",item_value);
|
||||
map_item = map.Next(map_item);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char* /*argv*/[])
|
||||
{
|
||||
int element_array[kNumberOfElements];
|
||||
for (int i = 0; i < kNumberOfElements; i++)
|
||||
{
|
||||
element_array[i] = i;
|
||||
}
|
||||
// Test insert
|
||||
MapWrapper test_map;
|
||||
for (int i = 0; i < kNumberOfElements; i++)
|
||||
{
|
||||
test_map.Insert(i,(void*)&element_array[i]);
|
||||
}
|
||||
// Test Erase1
|
||||
MapItem* remove_item = test_map.Find(2);
|
||||
FailTest(remove_item == NULL);
|
||||
FailTest(test_map.Erase(remove_item) != 0);
|
||||
FailTest(test_map.Find(2) != NULL);
|
||||
remove_item = NULL;
|
||||
FailTest(test_map.Erase(remove_item) != -1);
|
||||
// Test Erase2
|
||||
FailTest(test_map.Erase(1) != 0);
|
||||
FailTest(test_map.Find(1) != NULL);
|
||||
FailTest(test_map.Erase(1) != -1);
|
||||
// Test Size
|
||||
FailTest(test_map.Size() != kNumberOfElements - 2);
|
||||
PrintMap(test_map);
|
||||
// Test First
|
||||
MapItem* first_item = test_map.First();
|
||||
FailTest(first_item == NULL);
|
||||
FailTest(GetStoredIntegerValue(first_item) != 0);
|
||||
// Test Last
|
||||
MapItem* last_item = test_map.Last();
|
||||
FailTest(last_item == NULL);
|
||||
FailTest(GetStoredIntegerValue(last_item) != 9);
|
||||
// Test Next
|
||||
MapItem* second_item = test_map.Next(first_item);
|
||||
FailTest(second_item == NULL);
|
||||
FailTest(GetStoredIntegerValue(second_item) != 3);
|
||||
FailTest(test_map.Next(last_item) != NULL);
|
||||
// Test Previous
|
||||
MapItem* second_to_last_item = test_map.Previous(last_item);
|
||||
FailTest(second_to_last_item == NULL);
|
||||
FailTest(GetStoredIntegerValue(second_to_last_item) != 8);
|
||||
FailTest(test_map.Previous(first_item) != NULL);
|
||||
// Test Find (only improper usage untested)
|
||||
FailTest(test_map.Find(kNumberOfElements + 2) != NULL);
|
||||
// Test GetId
|
||||
FailTest(*(reinterpret_cast<int*>(second_to_last_item->GetItem())) !=
|
||||
second_to_last_item->GetId());
|
||||
FailTest(second_to_last_item->GetUnsignedId() !=
|
||||
static_cast<unsigned int>(second_to_last_item->GetId()));
|
||||
// Test SetItem
|
||||
int swapped_item = kNumberOfElements;
|
||||
last_item->SetItem(reinterpret_cast<void*>(&swapped_item));
|
||||
FailTest(GetStoredIntegerValue(last_item) !=
|
||||
swapped_item);
|
||||
|
||||
printf("Tests passed successfully!\n");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user