Make atomic add allow amounts not just +-1

This commit is contained in:
Doyle Thai 2017-06-26 12:37:52 +10:00
parent fca8db0366
commit 866126e735
2 changed files with 32 additions and 50 deletions

80
dqn.h
View File

@ -1093,13 +1093,15 @@ typedef struct DqnLock
void Release();
void Delete ();
// Create a lock guard on the lock this is invoked on.
struct DqnLockGuard LockGuard();
#endif
} DqnLock;
#if defined(DQN_CPP_MODE)
// Lock guard automatically acquires a lock on construction and releases a lock
// on destruction.
// Lock guard automatically acquires a lock on construction and releases the associated lock on
// destruction. If the lock is unable to be acquired, the program blocks at construction until it
// can.
struct DqnLockGuard
{
// lock: Takes a pointer to a pre-existing and already initialised lock
@ -1153,8 +1155,8 @@ typedef struct DqnJobQueue
u32 size;
// NOTE(doyle): Modified by main+worker threads
u32 volatile jobToExecuteIndex;
u32 volatile numJobsToComplete;
i32 volatile jobToExecuteIndex;
i32 volatile numJobsToComplete;
#if defined(DQN_WIN32_PLATFORM)
void *semaphore;
@ -1167,9 +1169,8 @@ typedef struct DqnJobQueue
#endif
// NOTE: Modified by main thread ONLY
u32 volatile jobInsertIndex;
i32 volatile jobInsertIndex;
#if defined(DQN_CPP_MODE)
bool Init (const DqnJob *const jobList_, const u32 jobListSize, const u32 numThreads);
@ -1217,15 +1218,11 @@ DQN_FILE_SCOPE bool DqnJobQueue_AllJobsComplete (DqnJobQueue *const queue);
// swapVal: The value to put into "dest", IF at point of read, "dest" has the value of "compareVal"
// compareVal: The value to check in "dest"
// return: Return the original value that was in "dest"
DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *const dest, const u32 swapVal, const u32 compareVal);
DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *const dest, const i32 swapVal, const i32 compareVal);
// Increment the value at src by 1
// return: The incremented value
DQN_FILE_SCOPE u32 DqnAtomic_Add32(u32 volatile *const src);
// Decrement the value at src by 1
// return: The decremented value
DQN_FILE_SCOPE u32 DqnAtomic_Sub32(u32 volatile *const src);
// Add "value" to src
// return: The new value at src
DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *const src, const i32 value);
////////////////////////////////////////////////////////////////////////////////
// XPlatform > #DqnPlatform Public API - Common Platform API Helpers
@ -6426,12 +6423,12 @@ DQN_FILE_SCOPE bool DqnJobQueue_Init(DqnJobQueue *const queue, DqnJob *const job
DQN_FILE_SCOPE bool DqnJobQueue_AddJob(DqnJobQueue *const queue, const DqnJob job)
{
u32 newJobInsertIndex = (queue->jobInsertIndex + 1) % queue->size;
i32 newJobInsertIndex = (queue->jobInsertIndex + 1) % queue->size;
if (newJobInsertIndex == queue->jobToExecuteIndex) return false;
queue->jobList[queue->jobInsertIndex] = job;
DqnAtomic_Add32(&queue->numJobsToComplete);
DqnAtomic_Add32(&queue->numJobsToComplete, 1);
DQN_ASSERT(DqnJobQueueInternal_ReleaseSemaphore(queue));
queue->jobInsertIndex = newJobInsertIndex;
@ -6448,11 +6445,11 @@ DQN_FILE_SCOPE bool DqnJobQueue_TryExecuteNextJob(DqnJobQueue *const queue)
{
if (!queue) return false;
u32 originalJobToExecute = queue->jobToExecuteIndex;
i32 originalJobToExecute = queue->jobToExecuteIndex;
if (originalJobToExecute != queue->jobInsertIndex)
{
u32 newJobIndexForNextThread = (originalJobToExecute + 1) % queue->size;
u32 index = DqnAtomic_CompareSwap32(&queue->jobToExecuteIndex, newJobIndexForNextThread,
i32 newJobIndexForNextThread = (originalJobToExecute + 1) % queue->size;
i32 index = DqnAtomic_CompareSwap32(&queue->jobToExecuteIndex, newJobIndexForNextThread,
originalJobToExecute);
// NOTE: If we weren't successful at the interlock, another thread has
@ -6463,7 +6460,7 @@ DQN_FILE_SCOPE bool DqnJobQueue_TryExecuteNextJob(DqnJobQueue *const queue)
{
DqnJob job = queue->jobList[index];
job.callback(queue, job.userData);
DqnAtomic_Sub32(&queue->numJobsToComplete);
DqnAtomic_Add32(&queue->numJobsToComplete, -1);
}
return true;
@ -6497,13 +6494,17 @@ bool DqnJobQueue::AllJobsComplete () { return DqnJobQueue_AllJo
////////////////////////////////////////////////////////////////////////////////
// XPlatform > #DqnAtomic Implementation
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *const dest, const u32 swapVal,
const u32 compareVal)
{
u32 result = 0;
#if defined(DQN_WIN32_PLATFORM)
DQN_ASSERT(sizeof(LONG) == sizeof(u32));
result = (u32)InterlockedCompareExchange((LONG volatile *)dest, (LONG)swapVal, (LONG)compareVal);
DQN_COMPILE_ASSERT(sizeof(LONG) == sizeof(i32));
#endif
DQN_FILE_SCOPE i32 DqnAtomic_CompareSwap32(i32 volatile *const dest, const i32 swapVal,
const i32 compareVal)
{
i32 result = 0;
#if defined(DQN_WIN32_PLATFORM)
result = (i32)InterlockedCompareExchange((LONG volatile *)dest, (LONG)swapVal, (LONG)compareVal);
#elif defined(DQN_UNIX_PLATFORM)
result = __sync_val_compare_and_swap(dest, compareVal, swapVal);
@ -6515,33 +6516,14 @@ DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *const dest, const u32 s
return result;
}
DQN_FILE_SCOPE u32 DqnAtomic_Add32(u32 volatile *const src)
DQN_FILE_SCOPE i32 DqnAtomic_Add32(i32 volatile *const src, const i32 value)
{
u32 result = 0;
i32 result = 0;
#if defined(DQN_WIN32_PLATFORM)
DQN_ASSERT(sizeof(LONG) == sizeof(u32));
result = (u32)InterlockedIncrement((LONG volatile *)src);
result = (i32)InterlockedAdd((LONG volatile *)src, value);
#elif defined(DQN_UNIX_PLATFORM)
result = __sync_add_and_fetch(src, 1);
#else
#error Unsupported platform
#endif
return result;
}
DQN_FILE_SCOPE u32 DqnAtomic_Sub32(u32 volatile *const src)
{
u32 result = 0;
#if defined(DQN_WIN32_PLATFORM)
DQN_ASSERT(sizeof(LONG) == sizeof(u32));
result = (u32)InterlockedDecrement((LONG volatile *)src);
#elif defined(DQN_UNIX_PLATFORM)
result = __sync_sub_and_fetch(src, 1);
result = __sync_add_and_fetch(src, value);
#else
#error Unsupported platform

View File

@ -21,7 +21,7 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release|x86
{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE