llcommon merge. Added LLUnits.

This commit is contained in:
Shyotl
2016-04-06 01:31:20 -05:00
parent 0fa7848b19
commit 0841479ccc
66 changed files with 1895 additions and 621 deletions

View File

@@ -230,9 +230,13 @@ set(llcommon_HEADER_FILES
llthreadsafequeue.h
lltimer.h
lltreeiterators.h
llunits.h
llunittype.h
lltypeinfolookup.h
lluri.h
lluuid.h
llwin32headers.h
llwin32headerslean.h
llworkerthread.h
metaclass.h
metaclasst.h

View File

@@ -64,7 +64,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::~LLAlignedArray()
{
ll_aligned_free(mArray);
ll_aligned_free<alignment>(mArray);
mArray = NULL;
mElementCount = 0;
mCapacity = 0;
@@ -78,7 +78,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
{
mCapacity++;
mCapacity *= 2;
T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
@@ -90,7 +90,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
mArray[mElementCount++] = elem;
//delete old array here to prevent error on a.push_back(a[0])
ll_aligned_free(old_buf);
ll_aligned_free<alignment>(old_buf);
}
template <class T, U32 alignment>
@@ -99,11 +99,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
if (mCapacity < size)
{
mCapacity = size+mCapacity*2;
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
ll_aligned_free(mArray);
ll_aligned_free<alignment>(mArray);
}
/*for (U32 i = mElementCount; i < mCapacity; ++i)

View File

@@ -30,32 +30,36 @@
#include "llbase64.h"
#include <string>
#include "apr_base64.h"
// static
std::string LLBase64::encode(const U8* input, size_t input_size)
{
if (!(input && input_size > 0)) return LLStringUtil::null;
// Yes, it returns int.
int b64_buffer_length = apr_base64_encode_len(input_size);
char* b64_buffer = new char[b64_buffer_length];
// This is faster than apr_base64_encode() if you know
// you're not on an EBCDIC machine. Also, the output is
// null terminated, even though the documentation doesn't
// specify. See apr_base64.c for details. JC
b64_buffer_length = apr_base64_encode_binary(
b64_buffer,
input,
input_size);
std::string result;
result.assign(b64_buffer);
delete[] b64_buffer;
return result;
std::string output;
if (input
&& input_size > 0)
{
// Yes, it returns int.
int b64_buffer_length = apr_base64_encode_len(input_size);
char* b64_buffer = new char[b64_buffer_length];
// This is faster than apr_base64_encode() if you know
// you're not on an EBCDIC machine. Also, the output is
// null terminated, even though the documentation doesn't
// specify. See apr_base64.c for details. JC
b64_buffer_length = apr_base64_encode_binary(
b64_buffer,
input,
input_size);
output.assign(b64_buffer);
delete[] b64_buffer;
}
return output;
}
// static
std::string LLBase64::encode(const std::string& in_str)
{

View File

@@ -55,8 +55,8 @@ LLDate::LLDate(const LLDate& date) :
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
{}
LLDate::LLDate(F64 seconds_since_epoch) :
mSecondsSinceEpoch(seconds_since_epoch)
LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
mSecondsSinceEpoch(seconds_since_epoch.value())
{}
LLDate::LLDate(const std::string& iso8601_date)
@@ -83,7 +83,7 @@ std::string LLDate::asString() const
// is one of the standards used and the prefered format
std::string LLDate::asRFC1123() const
{
return toHTTPDateString(LLStringExplicit("%A, %d %b %Y %H:%M:%S GMT"));
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");

View File

@@ -38,9 +38,8 @@
#include <iosfwd>
#include <string>
#include "llpreprocessor.h"
#include "stdtypes.h"
#include "llunits.h"
/**
* @class LLDate
@@ -64,9 +63,9 @@ public:
/**
* @brief Construct a date from a seconds since epoch value.
*
* @pararm seconds_since_epoch The number of seconds since UTC epoch.
* @param seconds_since_epoch The number of seconds since UTC epoch.
*/
LLDate(F64 seconds_since_epoch);
LLDate(F64SecondsImplicit seconds_since_epoch);
/**
* @brief Construct a date from a string representation
@@ -163,4 +162,6 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
// Helper function to stream in a date
LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
#endif // LL_LLDATE_H

View File

@@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer()
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
for (instance_iter iter = beginInstances(), iter_end = endInstances(); iter != iter_end;)
for (instance_iter iter = beginInstances(), end_iter = endInstances(); iter != end_iter;)
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();

View File

@@ -28,7 +28,7 @@
*/
#if LL_WINDOWS
#include <windows.h>
#include "llwin32headerslean.h"
#include <stdlib.h> // Windows errno
#else
#include <errno.h>

View File

@@ -39,7 +39,7 @@
#include <ctype.h>
#ifdef WIN32
#include <windows.h>
#include "llwin32headers.h"
#include <winnt.h>
#endif
@@ -183,7 +183,7 @@ canonise_fl(FL_Locale *l) {
#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
struct IDToCode {
LANGID id;
char* code;
const char* code;
};
static const IDToCode both_to_code[] = {
{ML(ENGLISH,US), "en_US.ISO_8859-1"},

View File

@@ -30,7 +30,8 @@
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
: LLLineBuffer(),
mMaxLines(max_lines)
mMaxLines(max_lines),
mMutex()
{
mTimer.reset();
}

View File

@@ -194,13 +194,6 @@ public:
return mHandle;
}
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
{
// provided here to enforce T deriving from LLHandleProvider<T>
}
template <typename U>
LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
{
@@ -209,6 +202,12 @@ protected:
return downcast_handle;
}
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
{
// provided here to enforce T deriving from LLHandleProvider<T>
}
private:
mutable LLRootHandle<T> mHandle;

View File

@@ -88,46 +88,51 @@ LLLiveFile::~LLLiveFile()
bool LLLiveFile::Impl::check()
{
if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod)
bool detected_change = false;
// Skip the check if not enough time has elapsed and we're not
// forcing a check of the file
if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
{
// Skip the check if not enough time has elapsed and we're not
// forcing a check of the file
return false;
}
mForceCheck = false;
mRefreshTimer.reset();
mForceCheck = false; // force only forces one check
mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed
// Stat the file to see if it exists and when it was last modified.
llstat stat_data;
int res = LLFile::stat(mFilename, &stat_data);
if (res)
{
// Couldn't stat the file, that means it doesn't exist or is
// broken somehow. Clear flags and return.
if (mLastExists)
{
mLastExists = false;
return true; // no longer existing is a change!
}
return false;
}
// The file exists, decide if we want to load it.
if (mLastExists)
{
// The file existed last time, don't read it if it hasn't changed since
// last time.
if (stat_data.st_mtime <= mLastModTime)
{
return false;
}
}
// We want to read the file. Update status info for the file.
mLastExists = true;
mLastStatTime = stat_data.st_mtime;
return true;
// Stat the file to see if it exists and when it was last modified.
llstat stat_data;
if (LLFile::stat(mFilename, &stat_data))
{
// Couldn't stat the file, that means it doesn't exist or is
// broken somehow.
if (mLastExists)
{
mLastExists = false;
detected_change = true; // no longer existing is a change!
LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL;
}
}
else
{
// The file exists
if ( ! mLastExists )
{
// last check, it did not exist - that counts as a change
LL_DEBUGS() << "detected created file '" << mFilename << "'" << LL_ENDL;
detected_change = true;
}
else if ( stat_data.st_mtime > mLastModTime )
{
// file modification time is newer than last check
LL_DEBUGS() << "detected updated file '" << mFilename << "'" << LL_ENDL;
detected_change = true;
}
mLastExists = true;
mLastStatTime = stat_data.st_mtime;
}
}
if (detected_change)
{
LL_INFOS() << "detected file change '" << mFilename << "'" << LL_ENDL;
}
return detected_change;
}
void LLLiveFile::Impl::changed()

View File

@@ -119,6 +119,12 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
buffer_space = 64 - buffer_index; // how much space is left in buffer
// now, transform each 64-byte piece of the input, bypassing the buffer
if (input == NULL || input_length == 0){
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
return;
}
// Transform as many times as possible.
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
// fill the rest of the buffer and transform
@@ -128,12 +134,6 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
buffer_space);
transform (buffer);
// now, transform each 64-byte piece of the input, bypassing the buffer
if (input == NULL || input_length == 0){
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
return;
}
for (input_index = buffer_space; input_index + 63 < input_length;
input_index += 64)
transform (input+input_index);

View File

@@ -32,7 +32,7 @@
//#endif
#if defined(LL_WINDOWS)
//# include <windows.h>
#include "llwin32headerslean.h"
# include <psapi.h>
#elif defined(LL_DARWIN)
# include <sys/types.h>
@@ -50,11 +50,11 @@
//static
char* LLMemory::reserveMem = 0;
U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
U32 LLMemory::sMaxPhysicalMemInKB = 0;
U32 LLMemory::sAllocatedMemInKB = 0;
U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
U32Kilobytes LLMemory::sAllocatedMemInKB(0);
U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
#if __DEBUG_PRIVATE_MEM__
@@ -93,9 +93,9 @@ void LLMemory::freeReserve()
}
//static
void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
{
sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
sMaxHeapSizeInKB = max_heap_size;
sEnableMemoryFailurePrevention = prevent_heap_failure ;
}
@@ -112,10 +112,10 @@ void LLMemory::updateMemoryInfo()
return ;
}
sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
U32 avail_phys, avail_virtual;
U32Kilobytes avail_phys, avail_virtual;
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
@@ -125,14 +125,16 @@ void LLMemory::updateMemoryInfo()
}
else
{
sAvailPhysicalMemInKB = 0 ;
sAvailPhysicalMemInKB = U32Kilobytes(0);
}
#else
//not valid for other systems for now.
sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
sMaxPhysicalMemInKB = U32_MAX ;
sAvailPhysicalMemInKB = U32_MAX ;
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
#endif
return ;
}
//
@@ -184,8 +186,8 @@ void LLMemory::logMemoryInfo(BOOL update)
//static
bool LLMemory::isMemoryPoolLow()
{
static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
static void* last_reserved_address = NULL ;
if(!sEnableMemoryFailurePrevention)
@@ -193,32 +195,32 @@ bool LLMemory::isMemoryPoolLow()
return false ; //no memory failure prevention.
}
if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
{
return true ;
}
if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
{
return true ;
}
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD
|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
//check the virtual address space fragmentation
if(!is_low)
{
if(!last_reserved_address)
{
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
}
else
{
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
if(!last_reserved_address) //failed, try once more
{
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
}
}
@@ -229,19 +231,19 @@ bool LLMemory::isMemoryPoolLow()
}
//static
U32 LLMemory::getAvailableMemKB()
U32Kilobytes LLMemory::getAvailableMemKB()
{
return sAvailPhysicalMemInKB ;
}
//static
U32 LLMemory::getMaxMemKB()
U32Kilobytes LLMemory::getMaxMemKB()
{
return sMaxPhysicalMemInKB ;
}
//static
U32 LLMemory::getAllocatedMemKB()
U32Kilobytes LLMemory::getAllocatedMemKB()
{
return sAllocatedMemInKB ;
}

View File

@@ -27,7 +27,8 @@
#define LLMEMORY_H
#include "linden_common.h"
#include "llunits.h"
#include "stdtypes.h"
#include <new>
#include <cstdlib>
#if !LL_WINDOWS
@@ -42,6 +43,21 @@ class LLMutex ;
#define LL_CHECK_MEMORY
#endif
#if LL_WINDOWS
#define LL_ALIGN_OF __alignof
#else
#define LL_ALIGN_OF __align_of__
#endif
#if LL_WINDOWS
#define LL_DEFAULT_HEAP_ALIGN 8
#elif LL_DARWIN
#define LL_DEFAULT_HEAP_ALIGN 16
#elif LL_LINUX
#define LL_DEFAULT_HEAP_ALIGN 8
#endif
//<singu>
// ll_assert_aligned seems to only exist to set breakpoints in case an alignment check fails.
// However, the implementation was horrible: the test was done using a integer modulo after
@@ -102,31 +118,43 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
inline void* ll_aligned_malloc( size_t size, int align )
{
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
void* mem = malloc( size + (align - 1) + sizeof(void*) );
char* aligned = ((char*)mem) + sizeof(void*);
aligned += align - ((uintptr_t)aligned & (align - 1));
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
// change preprocessor code to: #if 1 && defined(LL_WINDOWS)
((void**)aligned)[-1] = mem;
return aligned;
#endif
}
inline void ll_aligned_free( void* ptr )
{
#if defined(LL_WINDOWS)
_aligned_free(ptr);
#if 0 && defined(LL_WINDOWS)
void* ll_aligned_malloc_fallback( size_t size, int align );
void ll_aligned_free_fallback( void* ptr );
//------------------------------------------------------------------------------------------------
#else
if (ptr)
inline void* ll_aligned_malloc_fallback( size_t size, int align )
{
free( ((void**)ptr)[-1] );
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
void* mem = malloc( size + (align - 1) + sizeof(void*) );
char* aligned = ((char*)mem) + sizeof(void*);
aligned += align - ((uintptr_t)aligned & (align - 1));
((void**)aligned)[-1] = mem;
return aligned;
#endif
}
inline void ll_aligned_free_fallback( void* ptr )
{
#if defined(LL_WINDOWS)
_aligned_free(ptr);
#else
if (ptr)
{
free( ((void**)ptr)[-1] );
}
#endif
}
#endif
}
//------------------------------------------------------------------------------------------------
#if !LL_USE_TCMALLOC
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
@@ -189,7 +217,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
#if defined(LL_WINDOWS)
return _aligned_malloc(size, 32);
#elif defined(LL_DARWIN)
return ll_aligned_malloc( size, 32 );
return ll_aligned_malloc_fallback( size, 32 );
#else
void *rtn;
if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
@@ -204,12 +232,54 @@ inline void ll_aligned_free_32(void *p)
#if defined(LL_WINDOWS)
_aligned_free(p);
#elif defined(LL_DARWIN)
ll_aligned_free( p );
ll_aligned_free_fallback( p );
#else
free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
// general purpose dispatch functions that are forced inline so they can compile down to a single call
template<size_t ALIGNMENT>
LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
{
if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
{
return malloc(size);
}
else if (ALIGNMENT == 16)
{
return ll_aligned_malloc_16(size);
}
else if (ALIGNMENT == 32)
{
return ll_aligned_malloc_32(size);
}
else
{
return ll_aligned_malloc_fallback(size, ALIGNMENT);
}
}
template<size_t ALIGNMENT>
LL_FORCE_INLINE void ll_aligned_free(void* ptr)
{
if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
{
free(ptr);
}
else if (ALIGNMENT == 16)
{
ll_aligned_free_16(ptr);
}
else if (ALIGNMENT == 32)
{
return ll_aligned_free_32(ptr);
}
else
{
return ll_aligned_free_fallback(ptr);
}
}
// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
// Source and dest must be 16-byte aligned and size must be multiple of 16.
@@ -297,22 +367,22 @@ public:
static U64 getCurrentRSS();
static U32 getWorkingSetSize();
static void* tryToAlloc(void* address, U32 size);
static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
static void updateMemoryInfo() ;
static void logMemoryInfo(BOOL update = FALSE);
static bool isMemoryPoolLow();
static U32 getAvailableMemKB() ;
static U32 getMaxMemKB() ;
static U32 getAllocatedMemKB() ;
static U32Kilobytes getAvailableMemKB() ;
static U32Kilobytes getMaxMemKB() ;
static U32Kilobytes getAllocatedMemKB() ;
private:
static char* reserveMem;
static U32 sAvailPhysicalMemInKB ;
static U32 sMaxPhysicalMemInKB ;
static U32 sAllocatedMemInKB;
static U32 sAllocatedPageSizeInKB ;
static U32Kilobytes sAvailPhysicalMemInKB ;
static U32Kilobytes sMaxPhysicalMemInKB ;
static U32Kilobytes sAllocatedMemInKB;
static U32Kilobytes sAllocatedPageSizeInKB ;
static U32 sMaxHeapSizeInKB;
static U32Kilobytes sMaxHeapSizeInKB;
static BOOL sEnableMemoryFailurePrevention;
};

View File

@@ -34,6 +34,7 @@
#define LLMORTICIAN_H
#include "stdtypes.h"
#include <list>
class LL_COMMON_API LLMortician
{

View File

@@ -32,9 +32,7 @@
//#include <memory>
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
# include "llwin32headerslean.h"
# define _interlockedbittestandset _renamed_interlockedbittestandset
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
# include <intrin.h>
@@ -881,7 +879,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
LLProcessorInfo::~LLProcessorInfo() {}
F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }

View File

@@ -33,6 +33,8 @@
#ifndef LLPROCESSOR_H
#define LLPROCESSOR_H
#include "llunits.h"
class LLProcessorInfoImpl;
class LL_COMMON_API LLProcessorInfo
@@ -41,7 +43,7 @@ public:
LLProcessorInfo();
~LLProcessorInfo();
F64 getCPUFrequency() const;
F64MegahertzImplicit getCPUFrequency() const;
bool hasSSE() const;
bool hasSSE2() const;
bool hasAltivec() const;

View File

@@ -35,7 +35,7 @@
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
LLThread(name),
mThreaded(threaded),
mIdleThread(TRUE),
mIdleThread(true),
mNextHandle(0),
mStarted(FALSE)
{
@@ -552,14 +552,15 @@ void LLQueuedThread::run()
break;
}
mIdleThread = FALSE;
mIdleThread = false;
threadedUpdate();
int res = processNextRequest();
if (res == 0)
int pending_work = processNextRequest();
if (pending_work == 0)
{
mIdleThread = TRUE;
mIdleThread = true;
ms_sleep(1);
}
//LLThread::yield(); // thread should yield after each request

View File

@@ -32,8 +32,6 @@
#include <map>
#include <set>
#include "llapr.h"
#include "llthread.h"
#include "llsimplehash.h"
@@ -204,7 +202,7 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
LLAtomic32<bool> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
request_queue_t mRequestQueue;

View File

@@ -31,15 +31,15 @@
#if LL_REF_COUNT_DEBUG
#include "llthread.h"
#include "llapr.h"
#endif
LLRefCount::LLRefCount(const LLRefCount& other)
: mRef(0)
{
LLRefCount::LLRefCount(const LLRefCount& other) :
#if LL_REF_COUNT_DEBUG
mCrashAtUnlock = FALSE ;
mMutex(),
mCrashAtUnlock(FALSE),
#endif
mRef(0)
{
}
LLRefCount& LLRefCount::operator=(const LLRefCount&)
@@ -49,11 +49,12 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
}
LLRefCount::LLRefCount() :
#if LL_REF_COUNT_DEBUG
mMutex(),
mCrashAtUnlock(FALSE),
#endif
mRef(0)
{
#if LL_REF_COUNT_DEBUG
mCrashAtUnlock = FALSE ;
#endif
}
LLRefCount::~LLRefCount()

View File

@@ -337,10 +337,9 @@ void clear_eol(std::istream& input)
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
{
unsigned count = 0;
char c;
while (count < bufsize && input.good())
{
input.get(c);
char c = input.get();
buf[count++] = c;
if (is_eol(c))
break;

View File

@@ -39,7 +39,7 @@
#include <iostream>
#include <sstream>
#include "windows.h"
#include "llwin32headerslean.h"
#include "Dbghelp.h"
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(

View File

@@ -508,6 +508,27 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)
return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
}
/**
* Compare std::type_info* pointers a la std::less. We break this out as a
* separate function for use in two different std::less specializations.
*/
inline
bool before(const std::type_info* lhs, const std::type_info* rhs)
{
#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
// If we're building on Linux with gcc, and it's either gcc 3.x or
// 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on
// Mac too, and some people build with gcc on Windows (cygwin or mingw).
// On Linux, different load modules may produce different type_info*
// pointers for the same type. Have to compare name strings to get good
// results.
return strcmp(lhs->name(), rhs->name()) < 0;
#else // not Linux, or gcc 4.4+
// Just use before(), as we normally would
return lhs->before(*rhs) ? true : false;
#endif
}
/**
* Specialize std::less<std::type_info*> to use std::type_info::before().
* See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
@@ -522,7 +543,7 @@ namespace std
{
bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
{
return lhs->before(*rhs);
return before(lhs, rhs);
}
};
@@ -532,7 +553,7 @@ namespace std
{
bool operator()(std::type_info* lhs, std::type_info* rhs) const
{
return lhs->before(*rhs);
return before(lhs, rhs);
}
};
} // std

View File

@@ -30,9 +30,7 @@
#include "llerror.h"
#if LL_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include "llwin32headerslean.h"
#include <winnls.h> // for WideCharToMultiByte
#endif

View File

@@ -53,9 +53,7 @@
using namespace llsd;
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
# include "llwin32headerslean.h"
# include <psapi.h> // GetPerformanceInfo() et al.
# include <VersionHelpers.h>
#elif LL_DARWIN
@@ -705,7 +703,7 @@ LLMemoryInfo::LLMemoryInfo()
}
#if LL_WINDOWS
static U32 LLMemoryAdjustKBResult(U32 inKB)
static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
{
// Moved this here from llfloaterabout.cpp
@@ -716,16 +714,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
// returned from the GetMemoryStatusEx function. Here we keep the
// original adjustment from llfoaterabout.cpp until this can be
// fixed somehow.
inKB += 1024;
inKB += U32Megabytes(1);
return inKB;
}
#endif
U32 LLMemoryInfo::getPhysicalMemoryKB() const
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
#elif LL_DARWIN
// This might work on Linux as well. Someone check...
@@ -735,17 +733,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
size_t len = sizeof(phys);
sysctl(mib, 2, &phys, &len, NULL, 0);
return (U32)(phys >> 10);
return U64Bytes(phys);
#elif LL_LINUX
U64 phys = 0;
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
return (U32)(phys >> 10);
return U64Bytes(phys);
#elif LL_SOLARIS
U64 phys = 0;
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
return (U32)(phys >> 10);
return U64Bytes(phys);
#else
return 0;
@@ -753,32 +751,32 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
#endif
}
U32 LLMemoryInfo::getPhysicalMemoryClamped() const
U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
{
// Return the total physical memory in bytes, but clamp it
// to no more than U32_MAX
U32 phys_kb = getPhysicalMemoryKB();
if (phys_kb >= 4194304 /* 4GB in KB */)
U32Kilobytes phys_kb = getPhysicalMemoryKB();
if (phys_kb >= U32Gigabytes(4))
{
return U32_MAX;
return U32Bytes(U32_MAX);
}
else
{
return phys_kb << 10;
return phys_kb;
}
}
//static
void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
{
#if LL_WINDOWS
// Sigh, this shouldn't be a static method, then we wouldn't have to
// reload this data separately from refresh()
LLSD statsMap(loadStatsMap());
avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
#elif LL_DARWIN
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
@@ -795,8 +793,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
// Pageins: 2097212.
// Pageouts: 41759.
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
avail_physical_mem_kb = (U32Kilobytes)-1 ;
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#elif LL_LINUX
// mStatsMap is derived from MEMINFO_FILE:
@@ -847,15 +845,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
// DirectMap4k: 434168 kB
// DirectMap2M: 477184 kB
// (could also run 'free', but easier to read a file than run a program)
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
avail_physical_mem_kb = (U32Kilobytes)-1 ;
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#else
//do not know how to collect available memory info for other systems.
//leave it blank here for now.
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
avail_physical_mem_kb = (U32Kilobytes)-1 ;
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#endif
}

View File

@@ -112,15 +112,15 @@ public:
LLMemoryInfo(); ///< Default constructor
void stream(std::ostream& s) const; ///< output text info to s
U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes
U32Kilobytes getPhysicalMemoryKB() const;
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
** be returned.
*/
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
//get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
// Retrieve a map of memory statistics. The keys of the map are platform-
// dependent. The values are in kilobytes to try to avoid integer overflow.

View File

@@ -31,11 +31,9 @@
#include "u64.h"
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <winsock2.h>
# include <windows.h>
# include "llwin32headerslean.h"
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
# include <errno.h>
# include <errno.h>
# include <sys/time.h>
#else
# error "architecture not supported"
@@ -81,10 +79,10 @@ void ms_sleep(U32 ms)
U32 micro_sleep(U64 us, U32 max_yields)
{
// max_yields is unused; just fiddle with it to avoid warnings.
max_yields = 0;
ms_sleep(us / 1000);
return 0;
// max_yields is unused; just fiddle with it to avoid warnings.
max_yields = 0;
ms_sleep((U32)(us / 1000));
return 0;
}
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
static void _sleep_loop(struct timespec& thiswait)
@@ -216,56 +214,68 @@ U64 get_clock_count()
#endif
void update_clock_frequencies()
TimerInfo::TimerInfo()
: mClockFrequency(0.0),
mTotalTimeClockCount(0),
mLastTotalTimeClockCount(0)
{}
void TimerInfo::update()
{
gClockFrequency = calc_clock_frequency();
gClockFrequencyInv = 1.0/gClockFrequency;
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
mClockFrequency = calc_clock_frequency();
mClockFrequencyInv = 1.0/mClockFrequency;
mClocksToMicroseconds = mClockFrequencyInv;
}
TimerInfo& get_timer_info()
{
static TimerInfo sTimerInfo;
return sTimerInfo;
}
///////////////////////////////////////////////////////////////////////////////
// returns a U64 number that represents the number of
// microseconds since the Unix epoch - Jan 1, 1970
U64 totalTime()
U64MicrosecondsImplicit totalTime()
{
U64 current_clock_count = get_clock_count();
if (!gTotalTimeClockCount)
if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
{
update_clock_frequencies();
gTotalTimeClockCount = current_clock_count;
get_timer_info().update();
get_timer_info().mTotalTimeClockCount = current_clock_count;
#if LL_WINDOWS
// Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
// Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
// make in the future.
gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
#endif
// Update the last clock count
gLastTotalTimeClockCount = current_clock_count;
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
else
{
if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount))
if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
{
// No wrapping, we're all okay.
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
}
else
{
// We've wrapped. Compensate correctly
gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
}
// Update the last clock count
gLastTotalTimeClockCount = current_clock_count;
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
// Return the total clock tick count in microseconds.
return (U64)(gTotalTimeClockCount*gClocksToMicroseconds);
U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
return time;
}
@@ -273,9 +283,9 @@ U64 totalTime()
LLTimer::LLTimer()
{
if (!gClockFrequency)
if (!get_timer_info().mClockFrequency)
{
update_clock_frequencies();
get_timer_info().update();
}
mStarted = TRUE;
@@ -283,20 +293,32 @@ LLTimer::LLTimer()
}
LLTimer::~LLTimer()
{}
// static
void LLTimer::initClass()
{
if (!sTimer) sTimer = new LLTimer;
}
// static
U64 LLTimer::getTotalTime()
void LLTimer::cleanupClass()
{
delete sTimer; sTimer = NULL;
}
// static
U64MicrosecondsImplicit LLTimer::getTotalTime()
{
// simply call into the implementation function.
return totalTime();
U64MicrosecondsImplicit total_time = totalTime();
return total_time;
}
// static
F64 LLTimer::getTotalSeconds()
F64SecondsImplicit LLTimer::getTotalSeconds()
{
return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
return F64Microseconds(U64_to_F64(getTotalTime()));
}
void LLTimer::reset()
@@ -343,43 +365,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
}
F64 LLTimer::getElapsedTimeF64() const
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
{
U64 last = mLastClockCount;
return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
}
F32 LLTimer::getElapsedTimeF32() const
F32SecondsImplicit LLTimer::getElapsedTimeF32() const
{
return (F32)getElapsedTimeF64();
}
F64 LLTimer::getElapsedTimeAndResetF64()
F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
{
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
}
F32 LLTimer::getElapsedTimeAndResetF32()
F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
{
return (F32)getElapsedTimeAndResetF64();
}
///////////////////////////////////////////////////////////////////////////////
void LLTimer::setTimerExpirySec(F32 expiration)
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
{
mExpirationTicks = get_clock_count()
+ (U64)((F32)(expiration * gClockFrequency));
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
}
F32 LLTimer::getRemainingTimeF32() const
F32SecondsImplicit LLTimer::getRemainingTimeF32() const
{
U64 cur_ticks = get_clock_count();
if (cur_ticks > mExpirationTicks)
{
return 0.0f;
}
return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
}
@@ -392,7 +414,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration)
}
mExpirationTicks = cur_ticks
+ (U64)((F32)(expiration * gClockFrequency));
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
return TRUE;
}
@@ -491,20 +513,20 @@ BOOL is_daylight_savings()
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
{
S32 pacific_offset_hours;
S32Hours pacific_offset_hours;
if (pacific_daylight_time)
{
pacific_offset_hours = 7;
pacific_offset_hours = S32Hours(7);
}
else
{
pacific_offset_hours = 8;
pacific_offset_hours = S32Hours(8);
}
// We subtract off the PST/PDT offset _before_ getting
// "UTC" time, because this will handle wrapping around
// for 5 AM UTC -> 10 PM PDT of the previous day.
utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
utc_time -= S32SecondsImplicit(pacific_offset_hours);
// Internal buffer to PST/PDT (see above)
struct tm* internal_time = gmtime(&utc_time);
@@ -521,7 +543,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
}
void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
{
U64 hours;
U64 minutes;
@@ -543,9 +565,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
}
void secondsToTimecodeString(F32 current_time, std::string& tcstring)
void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
{
microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
microsecondsToTimecodeString(current_time, tcstring);
}

View File

@@ -37,6 +37,7 @@
#include <string>
#include <list>
// units conversions
#include "llunits.h"
#ifndef USEC_PER_SEC
const U32 USEC_PER_SEC = 1000000;
#endif
@@ -61,21 +62,28 @@ public:
LLTimer();
~LLTimer();
static void initClass() { if (!sTimer) sTimer = new LLTimer; }
static void cleanupClass() { delete sTimer; sTimer = NULL; }
static void initClass();
static void cleanupClass();
// Return a high precision number of seconds since the start of
// this application instance.
static F64 getElapsedSeconds()
static F64SecondsImplicit getElapsedSeconds()
{
if (sTimer)
{
return sTimer->getElapsedTimeF64();
}
else
{
return 0;
}
}
// Return a high precision usec since epoch
static U64 getTotalTime();
static U64MicrosecondsImplicit getTotalTime();
// Return a high precision seconds since epoch
static F64 getTotalSeconds();
static F64SecondsImplicit getTotalSeconds();
// MANIPULATORS
@@ -83,19 +91,19 @@ public:
void stop() { mStarted = FALSE; }
void reset(); // Resets the timer
void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
void setTimerExpirySec(F32 expiration);
void setTimerExpirySec(F32SecondsImplicit expiration);
BOOL checkExpirationAndReset(F32 expiration);
BOOL hasExpired() const;
F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
F64 getElapsedTimeAndResetF64();
F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
F64SecondsImplicit getElapsedTimeAndResetF64();
F32 getRemainingTimeF32() const;
F32SecondsImplicit getRemainingTimeF32() const;
static BOOL knownBadTimer();
// ACCESSORS
F32 getElapsedTimeF32() const; // Returns elapsed time in seconds
F64 getElapsedTimeF64() const; // Returns elapsed time in seconds
F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
bool getStarted() const { return mStarted; }
@@ -106,6 +114,20 @@ public:
//
// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
//
struct TimerInfo
{
TimerInfo();
void update();
F64HertzImplicit mClockFrequency;
F64SecondsImplicit mClockFrequencyInv;
F64MicrosecondsImplicit mClocksToMicroseconds;
U64 mTotalTimeClockCount;
U64 mLastTotalTimeClockCount;
};
TimerInfo& get_timer_info();
LL_COMMON_API U64 get_clock_count();
LL_COMMON_API F64 calc_clock_frequency();
LL_COMMON_API void update_clock_frequencies();
@@ -160,10 +182,10 @@ LL_COMMON_API BOOL is_daylight_savings();
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string &timestr);
LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string &timestr);
U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
#endif

129
indra/llcommon/llunits.h Normal file
View File

@@ -0,0 +1,129 @@
/**
* @file llunits.h
* @brief Unit definitions
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLUNITTYPE_H
#define LL_LLUNITTYPE_H
#include "stdtypes.h"
#include "llunittype.h"
//
// Unit declarations
//
namespace LLUnits
{
LL_DECLARE_BASE_UNIT(Bytes, "B");
// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024);
LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024);
LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
namespace LLUnits
{
// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
namespace LLUnits
{
LL_DECLARE_BASE_UNIT(Seconds, "s");
LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
namespace LLUnits
{
LL_DECLARE_BASE_UNIT(Meters, "m");
LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
namespace LLUnits
{
// rare units
LL_DECLARE_BASE_UNIT(Hertz, "Hz");
LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000);
LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000);
LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000);
LL_DECLARE_BASE_UNIT(Radians, "rad");
LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f);
LL_DECLARE_BASE_UNIT(Percent, "%");
LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
LL_DECLARE_BASE_UNIT(Triangles, "tris");
LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000);
} // namespace LLUnits
// rare units
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
#endif // LL_LLUNITTYPE_H

838
indra/llcommon/llunittype.h Normal file
View File

@@ -0,0 +1,838 @@
/**
* @file llunit.h
* @brief Unit conversion classes
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_UNITTYPE_H
#define LL_UNITTYPE_H
#include "stdtypes.h"
#include "llpreprocessor.h"
#include "llerror.h"
//lightweight replacement of type traits for simple type equality check
template<typename S, typename T>
struct LLIsSameType
{
static const bool value = false;
};
template<typename T>
struct LLIsSameType<T, T>
{
static const bool value = true;
};
// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
template<typename S, typename T>
struct LLResultTypeAdd
{
typedef LL_TYPEOF(S() + T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeSubtract
{
typedef LL_TYPEOF(S() - T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeMultiply
{
typedef LL_TYPEOF(S() * T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeDivide
{
typedef LL_TYPEOF(S() / T(1)) type_t;
};
template<typename S, typename T>
struct LLResultTypePromote
{
typedef LL_TYPEOF((true) ? S() : T()) type_t;
};
template<typename STORAGE_TYPE, typename UNITS>
struct LLUnit
{
typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
typedef STORAGE_TYPE storage_t;
typedef void is_unit_t;
// value initialization
LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
: mValue(value)
{}
LL_FORCE_INLINE static self_t convert(self_t v)
{
return v;
}
template<typename FROM_STORAGE_TYPE>
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
{
self_t result;
result.mValue = (STORAGE_TYPE)v.value();
return result;
}
template<typename FROM_UNITS>
LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
{
self_t result;
STORAGE_TYPE divisor = ll_convert_units(v, result);
result.mValue /= divisor;
return result;
}
template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
{
typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
LLUnit<result_storage_t, UNITS> result;
result_storage_t divisor = ll_convert_units(v, result);
result.value(result.value() / divisor);
return self_t(result.value());
}
// unit initialization and conversion
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
: mValue(convert(other).mValue)
{}
LL_FORCE_INLINE storage_t value() const
{
return mValue;
}
LL_FORCE_INLINE void value(storage_t value)
{
mValue = value;
}
template<typename NEW_UNITS>
storage_t valueInUnits()
{
return LLUnit<storage_t, NEW_UNITS>(*this).value();
}
template<typename NEW_UNITS>
void valueInUnits(storage_t value)
{
*this = LLUnit<storage_t, NEW_UNITS>(value);
}
LL_FORCE_INLINE void operator += (self_t other)
{
mValue += convert(other).mValue;
}
LL_FORCE_INLINE void operator -= (self_t other)
{
mValue -= convert(other).mValue;
}
LL_FORCE_INLINE void operator *= (storage_t multiplicand)
{
mValue *= multiplicand;
}
LL_FORCE_INLINE void operator *= (self_t multiplicand)
{
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
}
LL_FORCE_INLINE void operator /= (storage_t divisor)
{
mValue /= divisor;
}
void operator /= (self_t divisor)
{
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue == convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue != convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue < convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue <= convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue > convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return mValue >= convert(other).value();
}
protected:
storage_t mValue;
};
template<typename STORAGE_TYPE, typename UNITS>
std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
{
s << unit.value() << UNITS::getUnitLabel();
return s;
}
template<typename STORAGE_TYPE, typename UNITS>
std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
{
STORAGE_TYPE val;
s >> val;
unit.value(val);
return s;
}
template<typename STORAGE_TYPE, typename UNITS>
struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
{
typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
: base_t(value)
{}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
: base_t(other)
{}
// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
// this allows for interoperability with legacy code
LL_FORCE_INLINE operator storage_t() const
{
return base_t::value();
}
using base_t::operator +=;
LL_FORCE_INLINE void operator += (storage_t value)
{
base_t::mValue += value;
}
// this overload exists to explicitly catch use of another implicit unit
// without ambiguity between conversion to storage_t vs conversion to base_t
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
{
base_t::mValue += base_t::convert(other).value();
}
using base_t::operator -=;
LL_FORCE_INLINE void operator -= (storage_t value)
{
base_t::mValue -= value;
}
// this overload exists to explicitly catch use of another implicit unit
// without ambiguity between conversion to storage_t vs conversion to base_t
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
{
base_t::mValue -= base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue == base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue == base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator == (STORAGE_T other) const
{
return base_t::mValue == other;
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue != convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue != base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator != (STORAGE_T other) const
{
return base_t::mValue != other;
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue < base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue < base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator < (STORAGE_T other) const
{
return base_t::mValue < other;
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue <= base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue <= base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
{
return base_t::mValue <= other;
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue > base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue > base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator > (STORAGE_T other) const
{
return base_t::mValue > other;
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue >= base_t::convert(other).value();
}
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
{
return base_t::mValue >= base_t::convert(other).value();
}
template<typename STORAGE_T>
LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
{
return base_t::mValue >= other;
}
};
template<typename STORAGE_TYPE, typename UNITS>
std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
{
s << unit.value() << UNITS::getUnitLabel();
return s;
}
template<typename STORAGE_TYPE, typename UNITS>
std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
{
STORAGE_TYPE val;
s >> val;
unit = val;
return s;
}
template<typename S1, typename T1, typename S2, typename T2>
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
{
S2 divisor(1);
LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
|| !LLIsSameType<T1, typename T1::base_unit_t>::value
|| !LLIsSameType<T2, typename T2::base_unit_t>::value),
"conversion requires compatible units");
if (LLIsSameType<T1, T2>::value)
{
// T1 and T2 same type, just assign
out.value((S2)in.value());
}
else if (T1::sLevel > T2::sLevel)
{
// reduce T1
LLUnit<S2, typename T1::base_unit_t> new_in;
divisor *= (S2)ll_convert_units(in, new_in);
divisor *= (S2)ll_convert_units(new_in, out);
}
else
{
// reduce T2
LLUnit<S2, typename T2::base_unit_t> new_out;
divisor *= (S2)ll_convert_units(in, new_out);
divisor *= (S2)ll_convert_units(new_out, out);
}
return divisor;
}
template<typename T>
struct LLStorageType
{
typedef T type_t;
};
template<typename STORAGE_TYPE, typename UNITS>
struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
{
typedef STORAGE_TYPE type_t;
};
// all of these operators need to perform type promotion on the storage type of the units, so they
// cannot be expressed as operations on identical types with implicit unit conversion
// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
//
// operator +
//
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result += second;
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
{
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
{
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result += second;
return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result += second;
return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
result += second;
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
result += second;
return result;
}
//
// operator -
//
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result -= second;
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
{
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
{
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result -= second;
return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result -= second;
return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
result -= second;
return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
result -= second;
return result;
}
//
// operator *
//
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
{
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
return LLUnit<STORAGE_TYPE1, UNITS1>();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
{
return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
{
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
}
//
// operator /
//
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
return first.value() / first.convert(second).value();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
template<typename T>
struct LLGetUnitLabel
{
static const char* getUnitLabel() { return ""; }
};
template<typename T, typename STORAGE_T>
struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
{
static const char* getUnitLabel() { return T::getUnitLabel(); }
};
template<typename T>
struct LLUnitLinearOps
{
typedef LLUnitLinearOps<T> self_t;
LLUnitLinearOps(T val)
: mValue(val),
mDivisor(1)
{}
template<typename OTHER_T>
self_t operator * (OTHER_T other)
{
return mValue * other;
}
template<typename OTHER_T>
self_t operator / (OTHER_T other)
{
mDivisor *= other;
return *this;
}
template<typename OTHER_T>
self_t operator + (OTHER_T other)
{
mValue += other * mDivisor;
return *this;
}
template<typename OTHER_T>
self_t operator - (OTHER_T other)
{
mValue -= other * mDivisor;
return *this;
}
T mValue;
T mDivisor;
};
template<typename T>
struct LLUnitInverseLinearOps
{
typedef LLUnitInverseLinearOps<T> self_t;
LLUnitInverseLinearOps(T val)
: mValue(val),
mDivisor(1),
mMultiplicand(1)
{}
template<typename OTHER_T>
self_t operator * (OTHER_T other)
{
mDivisor *= other;
return *this;
}
template<typename OTHER_T>
self_t operator / (OTHER_T other)
{
mValue *= other;
mMultiplicand *= other;
return *this;
}
template<typename OTHER_T>
self_t operator + (OTHER_T other)
{
mValue -= other * mMultiplicand;
return *this;
}
template<typename OTHER_T>
self_t operator - (OTHER_T other)
{
mValue += other * mMultiplicand;
return *this;
}
T mValue;
T mDivisor;
T mMultiplicand;
};
#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
struct base_unit_name \
{ \
static const int sLevel = 0; \
typedef base_unit_name base_unit_t; \
static const char* getUnitLabel() { return unit_label; } \
template<typename T> \
static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
template<typename STORAGE_T, typename UNIT_T> \
static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
{ return LLUnit<STORAGE_T, base_unit_name>(value); } \
}
#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
struct unit_name \
{ \
static const int sLevel = base_unit_name::sLevel + 1; \
typedef base_unit_name base_unit_t; \
static const char* getUnitLabel() { return unit_label; } \
template<typename T> \
static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
template<typename STORAGE_T, typename UNIT_T> \
static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
{ return LLUnit<STORAGE_T, unit_name>(value); } \
}; \
\
template<typename S1, typename S2> \
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
{ \
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
LLUnitInverseLinearOps<result_storage_t> result = \
LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
return result.mDivisor; \
} \
\
template<typename S1, typename S2> \
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
{ \
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
LLUnitLinearOps<result_storage_t> result = \
LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
out = LLUnit<S2, unit_name>((S2)result.mValue); \
return result.mDivisor; \
}
#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \
typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
#endif //LL_UNITTYPE_H

View File

@@ -27,9 +27,7 @@
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
#if LL_WINDOWS
#undef WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include "llwin32headers.h"
#endif
#include "lldefs.h"

View File

@@ -0,0 +1,42 @@
/**
* @file llwin32headers.h
* @brief sanitized include of windows header files
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWS_H
#define LL_LLWINDOWS_H
#ifdef LL_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#undef WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
// reset to default, which is lean
#define WIN32_LEAN_AND_MEAN
#undef NOMINMAX
#endif
#endif

View File

@@ -0,0 +1,40 @@
/**
* @file llwin32headerslean.h
* @brief sanitized include of windows header files
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWS_H
#define LL_LLWINDOWS_H
#ifdef LL_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#undef NOMINMAX
#endif
#endif

View File

@@ -37,7 +37,7 @@
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
LLQueuedThread(name, threaded, should_pause)
{
mDeleteMutex = new LLMutex;
mDeleteMutex = new LLMutex();
}
LLWorkerThread::~LLWorkerThread()
@@ -199,6 +199,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(),
mWorkFlags(0)
{
if (!mWorkerThread)
@@ -345,10 +346,14 @@ bool LLWorkerClass::checkWork(bool aborting)
}
LLQueuedThread::status_t status = workreq->getStatus();
if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED)
if (status == LLWorkerThread::STATUS_ABORTED)
{
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
abort = true;
}
else if (status == LLWorkerThread::STATUS_COMPLETE)
{
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
abort = status == LLWorkerThread::STATUS_ABORTED;
}
else
{