Add basic atomic operations for refcounting, etc.
This commit is contained in:
parent
121ee38fde
commit
a7ce178eec
38
src/physfs.c
38
src/physfs.c
|
@ -96,6 +96,30 @@ static int externalAllocator = 0;
|
||||||
PHYSFS_Allocator allocator;
|
PHYSFS_Allocator allocator;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PHYSFS_NEED_ATOMIC_OP_FALLBACK
|
||||||
|
static inline int __PHYSFS_atomicAdd(int *ptrval, const int val)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
retval = *ptrval;
|
||||||
|
*ptrval = retval + val;
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
return retval;
|
||||||
|
} /* __PHYSFS_atomicAdd */
|
||||||
|
|
||||||
|
int __PHYSFS_ATOMIC_INCR(int *ptrval)
|
||||||
|
{
|
||||||
|
return __PHYSFS_atomicAdd(ptrval, 1);
|
||||||
|
} /* __PHYSFS_ATOMIC_INCR */
|
||||||
|
|
||||||
|
int __PHYSFS_ATOMIC_DECR(int *ptrval)
|
||||||
|
{
|
||||||
|
return __PHYSFS_atomicAdd(ptrval, -1);
|
||||||
|
} /* __PHYSFS_ATOMIC_DECR */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* PHYSFS_Io implementation for i/o to physical filesystem... */
|
/* PHYSFS_Io implementation for i/o to physical filesystem... */
|
||||||
|
|
||||||
/* !!! FIXME: maybe refcount the paths in a string pool? */
|
/* !!! FIXME: maybe refcount the paths in a string pool? */
|
||||||
|
@ -292,10 +316,7 @@ static PHYSFS_Io *memoryIo_duplicate(PHYSFS_Io *io)
|
||||||
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
/* !!! FIXME: want lockless atomic increment. */
|
__PHYSFS_ATOMIC_INCR(&info->refcount);
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
|
||||||
info->refcount++;
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
|
||||||
|
|
||||||
memset(newinfo, '\0', sizeof (*info));
|
memset(newinfo, '\0', sizeof (*info));
|
||||||
newinfo->buf = info->buf;
|
newinfo->buf = info->buf;
|
||||||
|
@ -316,7 +337,6 @@ static void memoryIo_destroy(PHYSFS_Io *io)
|
||||||
{
|
{
|
||||||
MemoryIoInfo *info = (MemoryIoInfo *) io->opaque;
|
MemoryIoInfo *info = (MemoryIoInfo *) io->opaque;
|
||||||
PHYSFS_Io *parent = info->parent;
|
PHYSFS_Io *parent = info->parent;
|
||||||
int should_die = 0;
|
|
||||||
|
|
||||||
if (parent != NULL)
|
if (parent != NULL)
|
||||||
{
|
{
|
||||||
|
@ -333,13 +353,7 @@ static void memoryIo_destroy(PHYSFS_Io *io)
|
||||||
/* we _are_ the parent. */
|
/* we _are_ the parent. */
|
||||||
assert(info->refcount > 0); /* even in a race, we hold a reference. */
|
assert(info->refcount > 0); /* even in a race, we hold a reference. */
|
||||||
|
|
||||||
/* !!! FIXME: want lockless atomic decrement. */
|
if (__PHYSFS_ATOMIC_DECR(&info->refcount) == 0)
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
|
||||||
info->refcount--;
|
|
||||||
should_die = (info->refcount == 0);
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
|
||||||
|
|
||||||
if (should_die)
|
|
||||||
{
|
{
|
||||||
void (*destruct)(void *) = info->destruct;
|
void (*destruct)(void *) = info->destruct;
|
||||||
void *buf = (void *) info->buf;
|
void *buf = (void *) info->buf;
|
||||||
|
|
|
@ -104,6 +104,22 @@ const void *__PHYSFS_winrtCalcBaseDir(void);
|
||||||
const void *__PHYSFS_winrtCalcPrefDir(void);
|
const void *__PHYSFS_winrtCalcPrefDir(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* atomic operations. */
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||||
|
#include <intrin.h>
|
||||||
|
PHYSFS_COMPILE_TIME_ASSERT(LongEqualsInt, sizeof (int) == sizeof (long));
|
||||||
|
#define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedIncrement((long*)ptrval)
|
||||||
|
#define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedDecrement((long*)ptrval)
|
||||||
|
#elif defined(__clang__) || (defined(__GNUC__) && (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100)) >= 40100))
|
||||||
|
#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_fetch_and_add(ptrval, 1)
|
||||||
|
#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_fetch_and_add(ptrval, -1)
|
||||||
|
#else
|
||||||
|
#define PHYSFS_NEED_ATOMIC_OP_FALLBACK 1
|
||||||
|
int __PHYSFS_ATOMIC_INCR(int *ptrval);
|
||||||
|
int __PHYSFS_ATOMIC_DECR(int *ptrval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface for small allocations. If you need a little scratch space for
|
* Interface for small allocations. If you need a little scratch space for
|
||||||
* a throwaway buffer or string, use this. It will make small allocations
|
* a throwaway buffer or string, use this. It will make small allocations
|
||||||
|
|
Loading…
Reference in New Issue