llcommon merge. Added LLUnits.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#else
|
||||
#include <errno.h>
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines)
|
||||
mMaxLines(max_lines),
|
||||
mMutex()
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LLMORTICIAN_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <list>
|
||||
|
||||
class LL_COMMON_API LLMortician
|
||||
{
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "windows.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "Dbghelp.h"
|
||||
|
||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ×tr);
|
||||
LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr);
|
||||
|
||||
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
129
indra/llcommon/llunits.h
Normal 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
838
indra/llcommon/llunittype.h
Normal 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
|
||||
@@ -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"
|
||||
|
||||
42
indra/llcommon/llwin32headers.h
Normal file
42
indra/llcommon/llwin32headers.h
Normal 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
|
||||
40
indra/llcommon/llwin32headerslean.h
Normal file
40
indra/llcommon/llwin32headerslean.h
Normal 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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user