@@ -198,7 +198,7 @@ public: | |||
size (other.size), | |||
allocatedBytes (other.allocatedBytes), | |||
channels (other.channels), | |||
allocatedData (static_cast<HeapBlock<char, true>&&> (other.allocatedData)), | |||
allocatedData (static_cast<HeapBlock<char>&&> (other.allocatedData)), | |||
isClear (other.isClear) | |||
{ | |||
memcpy (preallocatedChannelSpace, other.preallocatedChannelSpace, sizeof (preallocatedChannelSpace)); | |||
@@ -214,7 +214,7 @@ public: | |||
size = other.size; | |||
allocatedBytes = other.allocatedBytes; | |||
channels = other.channels; | |||
allocatedData = static_cast<HeapBlock<char, true>&&> (other.allocatedData); | |||
allocatedData = static_cast<HeapBlock<char>&&> (other.allocatedData); | |||
isClear = other.isClear; | |||
memcpy (preallocatedChannelSpace, other.preallocatedChannelSpace, sizeof (preallocatedChannelSpace)); | |||
other.numChannels = 0; | |||
@@ -323,14 +323,14 @@ public: | |||
If the required memory can't be allocated, this will throw a std::bad_alloc exception. | |||
*/ | |||
void setSize (int newNumChannels, | |||
bool setSize (int newNumChannels, | |||
int newNumSamples, | |||
bool keepExistingContent = false, | |||
bool clearExtraSpace = false, | |||
bool avoidReallocating = false) noexcept | |||
{ | |||
jassert (newNumChannels >= 0); | |||
jassert (newNumSamples >= 0); | |||
CARLA_SAFE_ASSERT_RETURN (newNumChannels >= 0, false); | |||
CARLA_SAFE_ASSERT_RETURN (newNumSamples >= 0, false); | |||
if (newNumSamples != size || newNumChannels != numChannels) | |||
{ | |||
@@ -341,7 +341,7 @@ public: | |||
if (keepExistingContent) | |||
{ | |||
HeapBlock<char, true> newData; | |||
HeapBlock<char> newData; | |||
newData.allocate (newTotalBytes, clearExtraSpace || isClear); | |||
const size_t numSamplesToCopy = (size_t) jmin (newNumSamples, size); | |||
@@ -375,8 +375,8 @@ public: | |||
} | |||
else | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN (allocatedData.allocate (newTotalBytes, clearExtraSpace || isClear), false); | |||
allocatedBytes = newTotalBytes; | |||
allocatedData.allocate (newTotalBytes, clearExtraSpace || isClear); | |||
channels = reinterpret_cast<float**> (allocatedData.getData()); | |||
} | |||
@@ -392,6 +392,8 @@ public: | |||
size = newNumSamples; | |||
numChannels = newNumChannels; | |||
} | |||
return true; | |||
} | |||
/** Makes this buffer point to a pre-allocated set of channel data arrays. | |||
@@ -412,12 +414,12 @@ public: | |||
@param newNumSamples the number of samples to use - this must correspond to the | |||
size of the arrays passed in | |||
*/ | |||
void setDataToReferTo (float** dataToReferTo, | |||
bool setDataToReferTo (float** dataToReferTo, | |||
const int newNumChannels, | |||
const int newNumSamples) noexcept | |||
{ | |||
jassert (dataToReferTo != nullptr); | |||
jassert (newNumChannels >= 0 && newNumSamples >= 0); | |||
CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN (newNumChannels >= 0 && newNumSamples >= 0, false); | |||
if (allocatedBytes != 0) | |||
{ | |||
@@ -428,8 +430,7 @@ public: | |||
numChannels = newNumChannels; | |||
size = newNumSamples; | |||
allocateChannels (dataToReferTo, 0); | |||
jassert (! isClear); | |||
return allocateChannels (dataToReferTo, 0); | |||
} | |||
/** Resizes this buffer to match the given one, and copies all of its content across. | |||
@@ -948,112 +949,22 @@ public: | |||
} | |||
} | |||
#if 0 | |||
/** Returns a Range indicating the lowest and highest sample values in a given section. | |||
@param channel the channel to read from | |||
@param startSample the start sample within the channel | |||
@param numSamples the number of samples to check | |||
*/ | |||
Range<float> findMinMax (int channel, | |||
int startSample, | |||
int numSamples) const noexcept | |||
{ | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
if (isClear) | |||
return Range<float>(); | |||
return FloatVectorOperations::findMinAndMax (channels [channel] + startSample, numSamples); | |||
} | |||
/** Finds the highest absolute sample value within a region of a channel. */ | |||
float getMagnitude (int channel, | |||
int startSample, | |||
int numSamples) const noexcept | |||
{ | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
if (isClear) | |||
return 0.0f; | |||
const Range<float> r (findMinMax (channel, startSample, numSamples)); | |||
return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd()); | |||
} | |||
/** Finds the highest absolute sample value within a region on all channels. */ | |||
float getMagnitude (int startSample, | |||
int numSamples) const noexcept | |||
{ | |||
float mag = 0.0f; | |||
if (! isClear) | |||
for (int i = 0; i < numChannels; ++i) | |||
mag = jmax (mag, getMagnitude (i, startSample, numSamples)); | |||
return mag; | |||
} | |||
/** Returns the root mean squared level for a region of a channel. */ | |||
float getRMSLevel (int channel, | |||
int startSample, | |||
int numSamples) const noexcept | |||
{ | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear) | |||
return 0.0f; | |||
const float* const data = channels [channel] + startSample; | |||
double sum = 0.0; | |||
for (int i = 0; i < numSamples; ++i) | |||
{ | |||
const float sample = data [i]; | |||
sum += sample * sample; | |||
} | |||
return (float) std::sqrt (sum / numSamples); | |||
} | |||
/** Reverses a part of a channel. */ | |||
void reverse (int channel, int startSample, int numSamples) const noexcept | |||
{ | |||
jassert (isPositiveAndBelow (channel, numChannels)); | |||
jassert (startSample >= 0 && startSample + numSamples <= size); | |||
if (! isClear) | |||
std::reverse (channels[channel] + startSample, | |||
channels[channel] + startSample + numSamples); | |||
} | |||
/** Reverses a part of the buffer. */ | |||
void reverse (int startSample, int numSamples) const noexcept | |||
{ | |||
for (int i = 0; i < numChannels; ++i) | |||
reverse (i, startSample, numSamples); | |||
} | |||
#endif | |||
private: | |||
//============================================================================== | |||
int numChannels, size; | |||
size_t allocatedBytes; | |||
float** channels; | |||
HeapBlock<char, true> allocatedData; | |||
HeapBlock<char> allocatedData; | |||
float* preallocatedChannelSpace [32]; | |||
bool isClear; | |||
void allocateData() | |||
bool allocateData() | |||
{ | |||
const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1); | |||
allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32; | |||
allocatedData.malloc (allocatedBytes); | |||
const size_t nextAllocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32; | |||
CARLA_SAFE_ASSERT_RETURN (allocatedData.malloc (nextAllocatedBytes), false); | |||
allocatedBytes = nextAllocatedBytes; | |||
channels = reinterpret_cast<float**> (allocatedData.getData()); | |||
float* chan = (float*) (allocatedData + channelListSize); | |||
@@ -1065,11 +976,12 @@ private: | |||
channels [numChannels] = nullptr; | |||
isClear = false; | |||
return true; | |||
} | |||
void allocateChannels (float* const* const dataToReferTo, int offset) | |||
bool allocateChannels (float* const* const dataToReferTo, int offset) | |||
{ | |||
jassert (offset >= 0); | |||
CARLA_SAFE_ASSERT_RETURN (offset >= 0, false); | |||
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) | |||
if (numChannels < (int) numElementsInArray (preallocatedChannelSpace)) | |||
@@ -1078,20 +990,21 @@ private: | |||
} | |||
else | |||
{ | |||
allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*)); | |||
CARLA_SAFE_ASSERT_RETURN( allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*)), false); | |||
channels = reinterpret_cast<float**> (allocatedData.getData()); | |||
} | |||
for (int i = 0; i < numChannels; ++i) | |||
{ | |||
// you have to pass in the same number of valid pointers as numChannels | |||
jassert (dataToReferTo[i] != nullptr); | |||
CARLA_SAFE_ASSERT_CONTINUE (dataToReferTo[i] != nullptr); | |||
channels[i] = dataToReferTo[i] + offset; | |||
} | |||
channels [numChannels] = nullptr; | |||
isClear = false; | |||
return true; | |||
} | |||
}; | |||
@@ -68,10 +68,10 @@ public: | |||
/** Creates a copy of another array. | |||
@param other the array to copy | |||
*/ | |||
Array (const Array<ElementType>& other) | |||
Array (const Array<ElementType>& other) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(data.setAllocatedSize (other.numUsed),); | |||
numUsed = other.numUsed; | |||
data.setAllocatedSize (other.numUsed); | |||
for (int i = 0; i < numUsed; ++i) | |||
new (data.elements + i) ElementType (other.data.elements[i]); | |||
@@ -91,10 +91,12 @@ public: | |||
@param values the array to copy from | |||
*/ | |||
template <typename TypeToCreateFrom> | |||
explicit Array (const TypeToCreateFrom* values) : numUsed (0) | |||
explicit Array (const TypeToCreateFrom* values) noexcept : numUsed (0) | |||
{ | |||
while (*values != TypeToCreateFrom()) | |||
add (*values++); | |||
{ | |||
CARLA_SAFE_ASSERT_BREAK(add (*values++)); | |||
} | |||
} | |||
/** Initalises from a C array of values. | |||
@@ -103,16 +105,16 @@ public: | |||
@param numValues the number of values in the array | |||
*/ | |||
template <typename TypeToCreateFrom> | |||
Array (const TypeToCreateFrom* values, int numValues) : numUsed (numValues) | |||
Array (const TypeToCreateFrom* values, int numValues) noexcept : numUsed (numValues) | |||
{ | |||
data.setAllocatedSize (numValues); | |||
CARLA_SAFE_ASSERT_RETURN(data.setAllocatedSize (numValues),); | |||
for (int i = 0; i < numValues; ++i) | |||
new (data.elements + i) ElementType (values[i]); | |||
} | |||
/** Destructor. */ | |||
~Array() | |||
~Array() noexcept | |||
{ | |||
deleteAllElements(); | |||
} | |||
@@ -120,7 +122,7 @@ public: | |||
/** Copies another array. | |||
@param other the array to copy | |||
*/ | |||
Array& operator= (const Array& other) | |||
Array& operator= (const Array& other) noexcept | |||
{ | |||
if (this != &other) | |||
{ | |||
@@ -180,7 +182,7 @@ public: | |||
@see clearQuick | |||
*/ | |||
void clear() | |||
void clear() noexcept | |||
{ | |||
deleteAllElements(); | |||
data.setAllocatedSize (0); | |||
@@ -190,7 +192,7 @@ public: | |||
/** Removes all elements from the array without freeing the array's allocated storage. | |||
@see clear | |||
*/ | |||
void clearQuick() | |||
void clearQuick() noexcept | |||
{ | |||
deleteAllElements(); | |||
numUsed = 0; | |||
@@ -365,10 +367,13 @@ public: | |||
@param newElement the new object to add to the array | |||
@see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray | |||
*/ | |||
void add (const ElementType& newElement) | |||
bool add (const ElementType& newElement) noexcept | |||
{ | |||
data.ensureAllocatedSize (numUsed + 1); | |||
if (! data.ensureAllocatedSize (numUsed + 1)) | |||
return false; | |||
new (data.elements + numUsed++) ElementType (newElement); | |||
return true; | |||
} | |||
#if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||
@@ -377,10 +382,13 @@ public: | |||
@param newElement the new object to add to the array | |||
@see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray | |||
*/ | |||
void add (ElementType&& newElement) | |||
bool add (ElementType&& newElement) noexcept | |||
{ | |||
data.ensureAllocatedSize (numUsed + 1); | |||
if (! data.ensureAllocatedSize (numUsed + 1)) | |||
return false; | |||
new (data.elements + numUsed++) ElementType (static_cast<ElementType&&> (newElement)); | |||
return true; | |||
} | |||
#endif | |||
@@ -396,10 +404,10 @@ public: | |||
@param newElement the new object to add to the array | |||
@see add, addSorted, addUsingDefaultSort, set | |||
*/ | |||
void insert (int indexToInsertAt, ParameterType newElement) | |||
bool insert (int indexToInsertAt, ParameterType newElement) noexcept | |||
{ | |||
data.ensureAllocatedSize (numUsed + 1); | |||
jassert (data.elements != nullptr); | |||
if (! data.ensureAllocatedSize (numUsed + 1)) | |||
return false; | |||
if (isPositiveAndBelow (indexToInsertAt, numUsed)) | |||
{ | |||
@@ -407,7 +415,7 @@ public: | |||
const int numberToMove = numUsed - indexToInsertAt; | |||
if (numberToMove > 0) | |||
memmove (insertPos + 1, insertPos, ((size_t) numberToMove) * sizeof (ElementType)); | |||
std::memmove (insertPos + 1, insertPos, ((size_t) numberToMove) * sizeof (ElementType)); | |||
new (insertPos) ElementType (newElement); | |||
++numUsed; | |||
@@ -416,6 +424,8 @@ public: | |||
{ | |||
new (data.elements + numUsed++) ElementType (newElement); | |||
} | |||
return true; | |||
} | |||
/** Inserts multiple copies of an element into the array at a given position. | |||
@@ -513,8 +523,7 @@ public: | |||
if (contains (newElement)) | |||
return false; | |||
add (newElement); | |||
return true; | |||
return add (newElement); | |||
} | |||
/** Replaces an element with a new value. | |||
@@ -1035,9 +1044,9 @@ public: | |||
removing elements, they may have quite a lot of unused space allocated. | |||
This method will reduce the amount of allocated storage to a minimum. | |||
*/ | |||
void minimiseStorageOverheads() | |||
bool minimiseStorageOverheads() noexcept | |||
{ | |||
data.shrinkToNoMoreThan (numUsed); | |||
return data.shrinkToNoMoreThan (numUsed); | |||
} | |||
/** Increases the array's internal storage to hold a minimum number of elements. | |||
@@ -1046,9 +1055,9 @@ public: | |||
the array won't have to keep dynamically resizing itself as the elements | |||
are added, and it'll therefore be more efficient. | |||
*/ | |||
void ensureStorageAllocated (const int minNumElements) | |||
bool ensureStorageAllocated (const int minNumElements) noexcept | |||
{ | |||
data.ensureAllocatedSize (minNumElements); | |||
return data.ensureAllocatedSize (minNumElements); | |||
} | |||
//============================================================================== | |||
@@ -39,9 +39,6 @@ namespace water { | |||
This class isn't really for public use - it's used by the other | |||
array classes, but might come in handy for some purposes. | |||
It inherits from a critical section class to allow the arrays to use | |||
the "empty base class optimisation" pattern to reduce their footprint. | |||
@see Array, OwnedArray, ReferenceCountedArray | |||
*/ | |||
template <class ElementType> | |||
@@ -83,17 +80,24 @@ public: | |||
@param numElements the number of elements that are needed | |||
*/ | |||
void setAllocatedSize (const int numElements) | |||
bool setAllocatedSize (const int numElements) noexcept | |||
{ | |||
if (numAllocated != numElements) | |||
{ | |||
if (numElements > 0) | |||
elements.realloc ((size_t) numElements); | |||
{ | |||
if (! elements.realloc ((size_t) numElements)) | |||
return false; | |||
} | |||
else | |||
{ | |||
elements.free(); | |||
} | |||
numAllocated = numElements; | |||
} | |||
return true; | |||
} | |||
/** Increases the amount of storage allocated if it is less than a given amount. | |||
@@ -104,21 +108,23 @@ public: | |||
@param minNumElements the minimum number of elements that are needed | |||
*/ | |||
void ensureAllocatedSize (const int minNumElements) | |||
bool ensureAllocatedSize (const int minNumElements) noexcept | |||
{ | |||
if (minNumElements > numAllocated) | |||
setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7); | |||
return setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7); | |||
jassert (numAllocated <= 0 || elements != nullptr); | |||
return true; | |||
} | |||
/** Minimises the amount of storage allocated so that it's no more than | |||
the given number of elements. | |||
*/ | |||
void shrinkToNoMoreThan (const int maxNumElements) | |||
bool shrinkToNoMoreThan (const int maxNumElements) noexcept | |||
{ | |||
if (maxNumElements < numAllocated) | |||
setAllocatedSize (maxNumElements); | |||
return setAllocatedSize (maxNumElements); | |||
return true; | |||
} | |||
/** Swap the contents of two objects. */ | |||
@@ -271,8 +271,9 @@ public: | |||
*/ | |||
ObjectClass* add (ObjectClass* newObject) noexcept | |||
{ | |||
data.ensureAllocatedSize (numUsed + 1); | |||
jassert (data.elements != nullptr); | |||
if (! data.ensureAllocatedSize (numUsed + 1)) | |||
return nullptr; | |||
data.elements [numUsed++] = newObject; | |||
return newObject; | |||
} | |||
@@ -303,14 +304,14 @@ public: | |||
if (indexToInsertAt > numUsed) | |||
indexToInsertAt = numUsed; | |||
data.ensureAllocatedSize (numUsed + 1); | |||
jassert (data.elements != nullptr); | |||
if (! data.ensureAllocatedSize (numUsed + 1)) | |||
return nullptr; | |||
ObjectClass** const e = data.elements + indexToInsertAt; | |||
const int numToMove = numUsed - indexToInsertAt; | |||
if (numToMove > 0) | |||
memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove); | |||
std::memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove); | |||
*e = newObject; | |||
++numUsed; | |||
@@ -369,8 +370,7 @@ public: | |||
if (contains (newObject)) | |||
return false; | |||
add (newObject); | |||
return true; | |||
return add (newObject) != nullptr; | |||
} | |||
/** Replaces an object in the array with a different one. | |||
@@ -771,9 +771,9 @@ public: | |||
removing elements, they may have quite a lot of unused space allocated. | |||
This method will reduce the amount of allocated storage to a minimum. | |||
*/ | |||
void minimiseStorageOverheads() noexcept | |||
bool minimiseStorageOverheads() noexcept | |||
{ | |||
data.shrinkToNoMoreThan (numUsed); | |||
return data.shrinkToNoMoreThan (numUsed); | |||
} | |||
/** Increases the array's internal storage to hold a minimum number of elements. | |||
@@ -782,9 +782,9 @@ public: | |||
the array won't have to keep dynamically resizing itself as the elements | |||
are added, and it'll therefore be more efficient. | |||
*/ | |||
void ensureStorageAllocated (const int minNumElements) noexcept | |||
bool ensureStorageAllocated (const int minNumElements) noexcept | |||
{ | |||
data.ensureAllocatedSize (minNumElements); | |||
return data.ensureAllocatedSize (minNumElements); | |||
} | |||
//============================================================================== | |||
@@ -70,14 +70,9 @@ namespace water { | |||
as their less object-oriented counterparts. Despite adding safety, you probably | |||
won't sacrifice any performance by using this in place of normal pointers. | |||
The throwOnFailure template parameter can be set to true if you'd like the class | |||
to throw a std::bad_alloc exception when an allocation fails. If this is false, | |||
then a failed allocation will just leave the heapblock with a null pointer (assuming | |||
that the system's malloc() function doesn't throw). | |||
@see Array, OwnedArray, MemoryBlock | |||
*/ | |||
template <class ElementType, bool throwOnFailure = false> | |||
template <class ElementType> | |||
class HeapBlock | |||
{ | |||
public: | |||
@@ -181,7 +176,7 @@ public: | |||
The data that is allocated will be freed when this object is deleted, or when you | |||
call free() or any of the allocation methods. | |||
*/ | |||
bool malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) | |||
bool malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) noexcept | |||
{ | |||
std::free (data); | |||
data = static_cast<ElementType*> (std::malloc (newNumElements * elementSize)); | |||
@@ -192,7 +187,7 @@ public: | |||
/** Allocates a specified amount of memory and clears it. | |||
This does the same job as the malloc() method, but clears the memory that it allocates. | |||
*/ | |||
bool calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) | |||
bool calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) noexcept | |||
{ | |||
std::free (data); | |||
data = static_cast<ElementType*> (std::calloc (newNumElements, elementSize)); | |||
@@ -204,7 +199,7 @@ public: | |||
This does the same job as either malloc() or calloc(), depending on the | |||
initialiseToZero parameter. | |||
*/ | |||
bool allocate (const size_t newNumElements, bool initialiseToZero) | |||
bool allocate (const size_t newNumElements, bool initialiseToZero) noexcept | |||
{ | |||
std::free (data); | |||
data = static_cast<ElementType*> (initialiseToZero | |||
@@ -219,7 +214,7 @@ public: | |||
The semantics of this method are the same as malloc() and calloc(), but it | |||
uses realloc() to keep as much of the existing data as possible. | |||
*/ | |||
bool realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) | |||
bool realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) noexcept | |||
{ | |||
data = static_cast<ElementType*> (data == nullptr ? std::malloc (newNumElements * elementSize) | |||
: std::realloc (data, newNumElements * elementSize)); | |||
@@ -238,8 +233,7 @@ public: | |||
/** Swaps this object's data with the data of another HeapBlock. | |||
The two objects simply exchange their data pointers. | |||
*/ | |||
template <bool otherBlockThrows> | |||
void swapWith (HeapBlock<ElementType, otherBlockThrows>& other) noexcept | |||
void swapWith (HeapBlock<ElementType>& other) noexcept | |||
{ | |||
std::swap (data, other.data); | |||
} | |||
@@ -24,6 +24,7 @@ | |||
*/ | |||
#include "Time.h" | |||
#include "../memory/Atomic.h" | |||
#include <ctime> | |||
#include <sys/time.h> | |||
@@ -38,7 +39,7 @@ namespace water { | |||
namespace TimeHelpers | |||
{ | |||
static uint32 lastMSCounterValue = 0; | |||
static Atomic<uint32> lastMSCounterValue; | |||
#ifdef CARLA_OS_MAC | |||
/* NB: these are kept outside the HiResCounterInfo struct and initialised to 1 to avoid | |||
@@ -129,12 +130,12 @@ uint32 Time::getMillisecondCounter() noexcept | |||
{ | |||
const uint32 now = water_millisecondsSinceStartup(); | |||
if (now < TimeHelpers::lastMSCounterValue) | |||
if (now < TimeHelpers::lastMSCounterValue.get()) | |||
{ | |||
// in multi-threaded apps this might be called concurrently, so | |||
// make sure that our last counter value only increases and doesn't | |||
// go backwards.. | |||
if (now < TimeHelpers::lastMSCounterValue - 1000) | |||
if (now < TimeHelpers::lastMSCounterValue.get() - 1000U) | |||
TimeHelpers::lastMSCounterValue = now; | |||
} | |||
else | |||
@@ -147,10 +148,8 @@ uint32 Time::getMillisecondCounter() noexcept | |||
uint32 Time::getApproximateMillisecondCounter() noexcept | |||
{ | |||
if (TimeHelpers::lastMSCounterValue == 0) | |||
getMillisecondCounter(); | |||
return TimeHelpers::lastMSCounterValue; | |||
const uint32 t = TimeHelpers::lastMSCounterValue.get(); | |||
return t == 0 ? getMillisecondCounter() : t; | |||
} | |||
} |