Turi Create  4.0
turi::deferred_rwlock Class Reference

#include <core/parallel/deferred_rwlock.hpp>

Public Member Functions

bool writelock_priority (request *I)
 
bool writelock (request *I)
 
void complete_wrlock ()
 
size_t complete_rdlock (request *&released)
 
size_t wrunlock (request *&released)
 
size_t readlock (request *I, request *&released)
 
size_t readlock_priority (request *I, request *&released)
 
size_t rdunlock (request *&released)
 

Detailed Description

The deferred rwlock is a variant of a regular rwlock which is completely non-blocking.

The user creates request objects:

// we use new here, but it is preferable that you have a big statically
// allocated pool of request objects
deferred_rwlock::request* request = new deferred_rwlock::request;
// request->id can be used here to associate additional information with the
// request. note that request->id is a 62 bit integer

After which, all lock acquisition / release operations return a released argument. For instance, to acquire a readlock

deferred_rwlock::request* released;
rwlock.readlock(request, &released);

or to complete a readlock:

deferred_rwlock::request* released;
rwlock.complete_rdlock(&released);

All operations are non-blocking, meaning that the lock request you issued/completed, need not be the set of requests that are satisfied. The set of released locks returned is a linked list of locks that are satisfied at completion of the operation.

For instance:

deferred_rwlock::request writelock;
deferred_rwlock::request readlocks[4];
deferred_rwlock::request* released;
// we are going to acquire a write lock
// this will be successful if rwlock is a fresh lock
bool success = rwlock.writelock(writelock);
// acquire 4 read locks consecutively. Note that this does not block.
// but since a write lock has already been acquired, all of these will
// return num_released = 0
int num_released;
num_released = rwlock.readlock(readlocks[0], &released);
num_released = rwlock.readlock(readlocks[1], &released);
num_released = rwlock.readlock(readlocks[2], &released);
num_released = rwlock.readlock(readlocks[3], &released);
// release the write lock we acquired earlier.
num_released = rwlock.wrunlock(writelock, &released);
// since the write lock is released, all readers can proceed and
// num_released will be 4 here. released now is a linked list of read requests.
// For instance, the following may be true:
released == &(readlocks[0]);
released->next == &(readlocks[1]);
released->next->next == &(readlocks[2]);
released->next->next->next == &(readlocks[3]);
released->next->next->next->next == nullptr;
// strictly the implementation need not have this particular linked list
// ordering, though that is indeed currently the case since it maintains
// a strict queue.
// At some point in the future you do need to call rdunlock() as many times
// as there are read requests completed.
rwlock.rdunlock();
rwlock.rdunlock();
rwlock.rdunlock();
rwlock.rdunlock();

This deferred_rwlock is tricky and not easy to use. You need to manage the request objects carefully and it is easy to get into inconsistent scenarios.

Definition at line 90 of file deferred_rwlock.hpp.

Member Function Documentation

◆ complete_rdlock()

size_t turi::deferred_rwlock::complete_rdlock ( request *&  released)
inline

completes the read lock on the head. lock must be acquired head must be a read lock

Definition at line 204 of file deferred_rwlock.hpp.

◆ complete_wrlock()

void turi::deferred_rwlock::complete_wrlock ( )
inline

completes the write lock on the head. lock must be acquired head must be a write lock

Definition at line 192 of file deferred_rwlock.hpp.

◆ rdunlock()

size_t turi::deferred_rwlock::rdunlock ( request *&  released)
inline

Released a currently acquired read lock. Returns the number of new locks acquired, and the output argument 'released' contains a linked list of locks next acquired,

Definition at line 336 of file deferred_rwlock.hpp.

◆ readlock()

size_t turi::deferred_rwlock::readlock ( request *  I,
request *&  released 
)
inline

Tries to acquire a readlock. Returns the number of locks now released. 'released' contains a linked list of locks next acquired,

Definition at line 276 of file deferred_rwlock.hpp.

◆ readlock_priority()

size_t turi::deferred_rwlock::readlock_priority ( request *  I,
request *&  released 
)
inline

Tries to acquire a high priority readlock. Returns the number of locks now released. 'released' contains a linked list of locks next acquired,

Definition at line 306 of file deferred_rwlock.hpp.

◆ writelock()

bool turi::deferred_rwlock::writelock ( request *  I)
inline

Tries to acquire a writelock. Returns true if the write lock is available immediately. False otherwise, in which case the request object may be returned in a released linked list via another complete lock operation.

Definition at line 170 of file deferred_rwlock.hpp.

◆ writelock_priority()

bool turi::deferred_rwlock::writelock_priority ( request *  I)
inline

Tries to acquire a high priority writelock. Returns true if the write lock is available immediately. False otherwise, in which case the request object may be returned in a released linked list via another complete lock operation.

Definition at line 147 of file deferred_rwlock.hpp.

◆ wrunlock()

size_t turi::deferred_rwlock::wrunlock ( request *&  released)
inline

Released a currently acquired write lock. Returns the number of new locks acquired, and the output argument 'released' contains a linked list of locks next acquired,

Definition at line 250 of file deferred_rwlock.hpp.


The documentation for this class was generated from the following file: