QReadWriteLock: cost of lockForRead, unlock and then maybe lockForWrite?



  • Hi,
    I'm just discovering QReadWriteLock.
    Would you do something like this

        _secureResultMap.lockForRead();
        Element *evolElement = _results.value(element, nullptr);
        _secureResultMap.unlock();
        if (evolElement)
        {
            QWriteLocker lockResultMap(&_secureResultMap);
            _results.remove(element);
            return evolElement;
        }
    

    Or would you rather go directly with QWriteLocker?
    (like this:

        QWriteLocker lockResultMap(&_secureResultMap);
        Element *evolElement = _results.value(element, nullptr);
        if (evolElement)
        {
            _results.remove(element);
            return evolElement;
        }
    

    I guess it depends on how often I would find the value in my map... well that is something I don't know yet...



  • Another example would be this:

    QSharedPointer<SharedObject> CentralizingWeakCache::getCentralizedValue(const QSharedPointer<SharedObject> &sharedPtr)
    {
        QSharedPointer<SharedObject> centralizedValue;
        QSharedPointer<WeakCacheKey> key(new WeakCacheKey(sharedPtr));
    
        _secureCache.lockForRead();
        QWeakPointer<SharedObject> cachedWeakPtr = _cache.value(key, QWeakPointer<SharedObject>());
        _secureCache.unlock();
        if (!cachedWeakPtr.isNull())
            centralizedValue = cachedWeakPtr.toStrongRef();
    
        if (centralizedValue.isNull())
        {
            centralizedValue = sharedPtr;
            centralizedValue->setCacheKey(this, key);
            QWriteLocker lockCache(&secureCache);
            _cache.insert(key, centralizedValue.toWeakRef());                
        }
    
        return centralizedValue;
    }
    

    In that case I know that I would have more reading than writing. A factor between 5 and 10.



  • @mbruel
    I've not used QReadWriteLock, and I may be putting my neck out here, but...

    In, say, your first example, you take a read lock, release it, and then lock for write, and use the result from the read lock (I guess that's what your title is about). Apart from the fact that is "slow", in general pattern you do not want to follow that approach. The whole point is that the value may be changed, deleted, whatever between you releasing the read lock and taking the new write lock. Unless you/someone else know better, that's a no-no as a pattern. You take your write lock, do you your update, then release, all atomic.



  • @JonB
    I see, you're right, for the remove I should lock for the whole operation.
    I guess in fact it is the same for the insert, another thread could insert the similar value in between and I could have some external object using it already.
    Cheers for this.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.