git-svn-id: http://webrtc.googlecode.com/svn/trunk@6 4adac7df-926f-26a2-2b94-8c16560cd09d

This commit is contained in:
niklase@google.com 2011-05-30 11:39:38 +00:00
parent 278733b2d9
commit f0779a2582
82 changed files with 11515 additions and 0 deletions

6
system_wrappers/OWNERS Normal file
View File

@ -0,0 +1,6 @@
hellner@google.com
pwestin@google.com
perkj@google.com
henrika@google.com
grunell@google.com
mflodman@google.com

View 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_

View 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_

View File

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

View 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_

View 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_

View File

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

View 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_

View File

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

View 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_

View File

@ -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_

View 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_

View File

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

View 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_

View 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_

View 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_

View 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_

View 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_

View 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

View 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

View 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_

View 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_

View 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_

View 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

View 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

View File

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

View 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

View 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_

View 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

View File

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

View 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

View File

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

View 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

View 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_

View 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",
&timestamp_sys_100_ns_type,
&timestamp_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_,
&timestamp_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

View 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_

View 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

View 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

View 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_

View 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

View File

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

View 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

View 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

View 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_

View 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

View File

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

View 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

View 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_

View 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

View 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_

View 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

View 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_

View 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

View 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

View File

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

View File

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

View 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

View File

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

View 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

View File

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

View 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

View 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_

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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:

View 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

View 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, &param);
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

View File

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

View 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

View 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_

View 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_

View 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

View 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_

View 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

View 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_

View 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

View 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_

View 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();
};

View 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;
}

View 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");
}

View 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");
}