Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualAndreas Jonsson

Posted 18 July 2013 - 04:20 PM

Yes, with a lockable critical section in the shared boolean I now believe the solution is thread-safe. Here's what the test class above now looks like (note, I didn't bother making the refCount itself thread-safe, but that is easily done with atomic instructions):

class MyClass
{
public:
    MyClass() { refCount = 1; weakRefFlag = 0; }
    ~MyClass()
    {
        if( weakRefFlag )
            weakRefFlag->Release();
    }
    void AddRef() { refCount++; }
    void Release() 
    {
        // If the weak ref flag exists it is because someone held a weak ref
        // and that someone may add a reference to the object at any time. It
        // is ok to check the existance of the weakRefFlag without locking here
        // because if the refCount is 1 then no other thread is currently 
        // creating the weakRefFlag.
        if( refCount == 1 && weakRefFlag )
        {
            // Set the flag to tell others that the object is no longer alive
            // We must do this before decreasing the refCount to 0 so we don't
            // end up with a race condition between this thread attempting to 
            // destroy the object and the other that temporary added a strong
            // ref from the weak ref.
            weakRefFlag->Set(true);
        }
 
        if( --refCount == 0 ) 
            delete this; 
    }
    asILockableSharedBool *GetWeakRefFlag()
    {
        if( !weakRefFlag )
        {
            // Lock globally so no other thread can attempt
            // to create a shared bool at the same time
            asAcquireExclusiveLock();
 
            // Make sure another thread didn't create the 
            // flag while we waited for the lock
            if( !weakRefFlag )
                weakRefFlag = asCreateLockableSharedBool();
 
            asReleaseExclusiveLock();
        }
 
        return weakRefFlag;
    }
 
    static MyClass *Factory() { return new MyClass(); }
 
protected:
    int refCount;
    asILockableSharedBool *weakRefFlag;
};

The implementation of the weakref add-on can be seen in the SVN.

 

 

If anyone can think of why this wouldn't be thread-safe, please let me know so I can fix it before releasing version 2.27.0. If you can think of a better solution I would also very much like to see that.


#1Andreas Jonsson

Posted 18 July 2013 - 04:18 PM

Yes, with a lockable critical section in the shared boolean I now believe the solution is thread-safe. Here's what the test class above now looks like (note, I didn't bother making the refCount itself thread-safe, but that is easily done with atomic instructions):

 

class MyClass
{
public:
    MyClass() { refCount = 1; weakRefFlag = 0; }
    ~MyClass()
    {
        if( weakRefFlag )
            weakRefFlag->Release();
    }
    void AddRef() { refCount++; }
    void Release() 
    {
        // If the weak ref flag exists it is because someone held a weak ref
        // and that someone may add a reference to the object at any time. It
        // is ok to check the existance of the weakRefFlag without locking here
        // because if the refCount is 1 then no other thread is currently 
        // creating the weakRefFlag.
        if( refCount == 1 && weakRefFlag )
        {
            // Set the flag to tell others that the object is no longer alive
            // We must do this before decreasing the refCount to 0 so we don't
            // end up with a race condition between this thread attempting to 
            // destroy the object and the other that temporary added a strong
            // ref from the weak ref.
            weakRefFlag->Set(true);
        }
 
        if( --refCount == 0 ) 
            delete this; 
    }
    asILockableSharedBool *GetWeakRefFlag()
    {
        if( !weakRefFlag )
        {
            // Lock globally so no other thread can attempt
            // to create a shared bool at the same time
            asAcquireExclusiveLock();
 
            // Make sure another thread didn't create the 
            // flag while we waited for the lock
            if( !weakRefFlag )
                weakRefFlag = asCreateLockableSharedBool();
 
            asReleaseExclusiveLock();
        }
 
        return weakRefFlag;
    }
 
    static MyClass *Factory() { return new MyClass(); }
 
protected:
    int refCount;
    asILockableSharedBool *weakRefFlag;
};

PARTNERS