Use C++11 atomics in place of AngelScript's implementation
AngelScript's implementation uses now-deprecated `OSAtomicIncrement32` and generates compiler warnings.
This commit is contained in:
parent
c7fb662f77
commit
6426247f09
@ -444,14 +444,14 @@ int CScriptAny::AddRef() const
|
||||
{
|
||||
// Increase counter and clear flag set by GC
|
||||
gcFlag = false;
|
||||
return asAtomicInc(refCount);
|
||||
return refCount.fetch_add(1) + 1;
|
||||
}
|
||||
|
||||
int CScriptAny::Release() const
|
||||
{
|
||||
// Decrease the ref counter
|
||||
gcFlag = false;
|
||||
if( asAtomicDec(refCount) == 0 )
|
||||
if( refCount.fetch_sub(1) == 1 )
|
||||
{
|
||||
// Delete this object as no more references to it exists
|
||||
delete this;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "angelscript.h"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
@ -48,7 +49,7 @@ protected:
|
||||
virtual ~CScriptAny();
|
||||
void FreeObject();
|
||||
|
||||
mutable int refCount;
|
||||
mutable std::atomic<int> refCount;
|
||||
mutable bool gcFlag;
|
||||
asIScriptEngine *engine;
|
||||
|
||||
|
@ -1719,14 +1719,14 @@ void CScriptArray::AddRef() const
|
||||
{
|
||||
// Clear the GC flag then increase the counter
|
||||
gcFlag = false;
|
||||
asAtomicInc(refCount);
|
||||
refCount.fetch_add(1);
|
||||
}
|
||||
|
||||
void CScriptArray::Release() const
|
||||
{
|
||||
// Clearing the GC flag then descrease the counter
|
||||
gcFlag = false;
|
||||
if( asAtomicDec(refCount) == 0 )
|
||||
if( refCount.fetch_sub(1) == 1 )
|
||||
{
|
||||
// When reaching 0 no more references to this instance
|
||||
// exists and the object should be destroyed
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "angelscript.h"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
// Sometimes it may be desired to use the same method names as used by C++ STL.
|
||||
// This may for example reduce time when converting code from script to C++ or
|
||||
// back.
|
||||
@ -100,7 +102,7 @@ public:
|
||||
void ReleaseAllHandles(asIScriptEngine *engine);
|
||||
|
||||
protected:
|
||||
mutable int refCount;
|
||||
mutable std::atomic<int> refCount;
|
||||
mutable bool gcFlag;
|
||||
asITypeInfo *objType;
|
||||
SArrayBuffer *buffer;
|
||||
|
@ -186,14 +186,14 @@ void CScriptDictionary::AddRef() const
|
||||
{
|
||||
// We need to clear the GC flag
|
||||
gcFlag = false;
|
||||
asAtomicInc(refCount);
|
||||
refCount.fetch_add(1);
|
||||
}
|
||||
|
||||
void CScriptDictionary::Release() const
|
||||
{
|
||||
// We need to clear the GC flag
|
||||
gcFlag = false;
|
||||
if( asAtomicDec(refCount) == 0 )
|
||||
if( refCount.fetch_sub(1) == 1 )
|
||||
{
|
||||
this->~CScriptDictionary();
|
||||
asFreeMem(const_cast<CScriptDictionary*>(this));
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "angelscript.h"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
// By default the CScriptDictionary use the std::string for the keys.
|
||||
// If the application uses a custom string type, then this typedef
|
||||
// can be changed accordingly. Remember, if the application uses
|
||||
@ -218,7 +220,7 @@ protected:
|
||||
|
||||
// Our properties
|
||||
asIScriptEngine *engine;
|
||||
mutable int refCount;
|
||||
mutable std::atomic<int> refCount;
|
||||
mutable bool gcFlag;
|
||||
dictMap_t dict;
|
||||
};
|
||||
|
@ -568,8 +568,6 @@ extern "C"
|
||||
AS_API void asReleaseExclusiveLock();
|
||||
AS_API void asAcquireSharedLock();
|
||||
AS_API void asReleaseSharedLock();
|
||||
AS_API int asAtomicInc(int &value);
|
||||
AS_API int asAtomicDec(int &value);
|
||||
AS_API int asThreadCleanup();
|
||||
|
||||
// Memory management
|
||||
|
@ -38,142 +38,5 @@
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
asCAtomic::asCAtomic()
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
asDWORD asCAtomic::get() const
|
||||
{
|
||||
// A very high ref count is highly unlikely. It most likely a problem with
|
||||
// memory that has been overwritten or is being accessed after it was deleted.
|
||||
asASSERT(value < 1000000);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void asCAtomic::set(asDWORD val)
|
||||
{
|
||||
// A very high ref count is highly unlikely. It most likely a problem with
|
||||
// memory that has been overwritten or is being accessed after it was deleted.
|
||||
asASSERT(value < 1000000);
|
||||
|
||||
value = val;
|
||||
}
|
||||
|
||||
asDWORD asCAtomic::atomicInc()
|
||||
{
|
||||
// A very high ref count is highly unlikely. It most likely a problem with
|
||||
// memory that has been overwritten or is being accessed after it was deleted.
|
||||
asASSERT(value < 1000000);
|
||||
|
||||
return asAtomicInc((int&)value);
|
||||
}
|
||||
|
||||
asDWORD asCAtomic::atomicDec()
|
||||
{
|
||||
// A very high ref count is highly unlikely. It most likely a problem with
|
||||
// memory that has been overwritten or is being accessed after it was deleted.
|
||||
asASSERT(value < 1000000);
|
||||
|
||||
return asAtomicDec((int&)value);
|
||||
}
|
||||
|
||||
//
|
||||
// The following code implements the atomicInc and atomicDec on different platforms
|
||||
//
|
||||
#if defined(AS_NO_THREADS) || defined(AS_NO_ATOMIC)
|
||||
|
||||
int asAtomicInc(int &value)
|
||||
{
|
||||
return ++value;
|
||||
}
|
||||
|
||||
int asAtomicDec(int &value)
|
||||
{
|
||||
return --value;
|
||||
}
|
||||
|
||||
#elif defined(AS_XENON) /// XBox360
|
||||
|
||||
END_AS_NAMESPACE
|
||||
#include <xtl.h>
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
int asAtomicInc(int &value)
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&value);
|
||||
}
|
||||
|
||||
int asAtomicDec(int &value)
|
||||
{
|
||||
return InterlockedDecrement((LONG*)&value);
|
||||
}
|
||||
|
||||
#elif defined(AS_WIN)
|
||||
|
||||
END_AS_NAMESPACE
|
||||
#define WIN32_MEAN_AND_LEAN
|
||||
#include <windows.h>
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
int asAtomicInc(int &value)
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&value);
|
||||
}
|
||||
|
||||
int asAtomicDec(int &value)
|
||||
{
|
||||
asASSERT(value > 0);
|
||||
return InterlockedDecrement((LONG*)&value);
|
||||
}
|
||||
|
||||
#elif defined(AS_LINUX) || defined(AS_BSD) || defined(AS_ILLUMOS) || defined(AS_ANDROID)
|
||||
|
||||
//
|
||||
// atomic_inc_and_test() and atomic_dec_and_test() from asm/atomic.h is not meant
|
||||
// to be used outside the Linux kernel. Instead we should use the GNUC provided
|
||||
// __sync_add_and_fetch() and __sync_sub_and_fetch() functions.
|
||||
//
|
||||
// Reference: http://golubenco.org/blog/atomic-operations/
|
||||
//
|
||||
// These are only available in GCC 4.1 and above, so for older versions we
|
||||
// use the critical sections, though it is a lot slower.
|
||||
//
|
||||
|
||||
int asAtomicInc(int &value)
|
||||
{
|
||||
return __sync_add_and_fetch(&value, 1);
|
||||
}
|
||||
|
||||
int asAtomicDec(int &value)
|
||||
{
|
||||
return __sync_sub_and_fetch(&value, 1);
|
||||
}
|
||||
|
||||
#elif defined(AS_MAC) || defined(AS_IPHONE)
|
||||
|
||||
END_AS_NAMESPACE
|
||||
#include <libkern/OSAtomic.h>
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
int asAtomicInc(int &value)
|
||||
{
|
||||
return OSAtomicIncrement32((int32_t*)&value);
|
||||
}
|
||||
|
||||
int asAtomicDec(int &value)
|
||||
{
|
||||
return OSAtomicDecrement32((int32_t*)&value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// If we get here, then the configuration in as_config.h
|
||||
// is wrong for the compiler/platform combination.
|
||||
int ERROR_PleaseFixTheConfig[-1];
|
||||
|
||||
#endif
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#ifndef AS_ATOMIC_H
|
||||
#define AS_ATOMIC_H
|
||||
|
||||
#include <atomic>
|
||||
#include "as_config.h"
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
@ -49,19 +50,19 @@ BEGIN_AS_NAMESPACE
|
||||
class asCAtomic
|
||||
{
|
||||
public:
|
||||
asCAtomic();
|
||||
asCAtomic() {}
|
||||
|
||||
asDWORD get() const;
|
||||
void set(asDWORD val);
|
||||
asDWORD get() const { return value.load(); }
|
||||
void set(asDWORD val) { value.store(val); }
|
||||
|
||||
// Increase and return new value
|
||||
asDWORD atomicInc();
|
||||
asDWORD atomicInc() { return value.fetch_add(1) + 1; }
|
||||
|
||||
// Decrease and return new value
|
||||
asDWORD atomicDec();
|
||||
asDWORD atomicDec() { return value.fetch_sub(1) - 1; }
|
||||
|
||||
protected:
|
||||
asDWORD value;
|
||||
std::atomic<asDWORD> value {0};
|
||||
};
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
@ -28,20 +28,20 @@ namespace spades {
|
||||
|
||||
RefCountedObject::~RefCountedObject() {}
|
||||
|
||||
void RefCountedObject::AddRef() { asAtomicInc(refCount); }
|
||||
void RefCountedObject::AddRef() { refCount.fetch_add(1); }
|
||||
|
||||
void RefCountedObject::Release() {
|
||||
#if DEBUG_REFCOUNTED_OBJECT_LAST_RELEASE
|
||||
AutoLocker guard(&releaseInfoMutex);
|
||||
#endif
|
||||
int cnt = asAtomicDec(refCount);
|
||||
if (cnt == 0) {
|
||||
int cnt = refCount.fetch_sub(1);
|
||||
if (cnt == 1) {
|
||||
#if DEBUG_REFCOUNTED_OBJECT_LAST_RELEASE
|
||||
|
||||
#else
|
||||
delete this;
|
||||
#endif
|
||||
} else if (cnt < 0)
|
||||
} else if (cnt < 1)
|
||||
#if DEBUG_REFCOUNTED_OBJECT_LAST_RELEASE
|
||||
SPRaise("Attempted to release already destroyed object\n===== LAST RELEASE BACKTRACE "
|
||||
"=====\n%s\n===== SECOND LAST RELEASE BACKTRACE =====\n%s\n===== LAST RELEASE "
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
@ -31,7 +32,7 @@
|
||||
namespace spades {
|
||||
|
||||
class RefCountedObject {
|
||||
int refCount;
|
||||
std::atomic<int> refCount;
|
||||
#if DEBUG_REFCOUNTED_OBJECT_LAST_RELEASE
|
||||
reflection::BacktraceRecord lastRelease;
|
||||
reflection::BacktraceRecord secondLastRelease;
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "ScriptManager.h"
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <Core/Debug.h>
|
||||
#include <Core/Math.h>
|
||||
@ -29,7 +30,8 @@ namespace spades {
|
||||
template <typename T>
|
||||
class PrimitiveArray {
|
||||
std::vector<T> inner;
|
||||
int refCount = 1;
|
||||
std::atomic<int> refCount {1};
|
||||
bool gcFlag = false;
|
||||
public:
|
||||
static asITypeInfo *scrType;
|
||||
typedef PrimitiveArray<T> ArrayType;
|
||||
@ -83,23 +85,24 @@ namespace spades {
|
||||
}
|
||||
|
||||
void AddRef() {
|
||||
refCount &= 0x7fffffff;
|
||||
asAtomicInc(refCount);
|
||||
gcFlag = false;
|
||||
refCount.fetch_add(1);
|
||||
}
|
||||
void Release() {
|
||||
refCount &= 0x7fffffff;
|
||||
gcFlag = false;
|
||||
|
||||
if(asAtomicDec(refCount) <= 0)
|
||||
if(refCount.fetch_sub(1) == 1) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
void SetGCFlag() {
|
||||
refCount |= 0x80000000;
|
||||
gcFlag = true;
|
||||
}
|
||||
bool GetGCFlag() {
|
||||
return (refCount & 0x80000000) != 0;
|
||||
return gcFlag;
|
||||
}
|
||||
int GetRefCount() {
|
||||
return refCount & 0x7fffffff;
|
||||
return refCount;
|
||||
}
|
||||
void EnumReferences(asIScriptEngine *eng) {}
|
||||
void ReleaseAllReferences(asIScriptEngine *eng){}
|
||||
|
Loading…
x
Reference in New Issue
Block a user