Docs: Qutex updated notes -- still WIP

This commit is contained in:
2025-09-19 01:18:19 -04:00
parent 2dfa615eb7
commit b9322c5e89
+24 -22
View File
@@ -171,16 +171,18 @@ we can implement a LockSet::registerAndTryAcquireAll() method, but that's for
us to think about later. us to think about later.
``` ```
/* We'll need to rename current class LockSpec to LockSet. */
class LockSet class LockSet
{ {
/* Add this either inside of LockSet or outside of it -- depends on whether /* Add this either inside of LockSet or outside of it -- depends on whether
* it's we can get it to compile because I'm seeing some potential circular * it's we can get it to compile because I'm seeing some potential circular
* definition dependencies. * definition dependencies.
*/ */
typedef std::pair<TicketLock, LockDesc> LockDesc; typedef std::pair<Qutex, LockerAndInvokerList::iterator>
LockUsageDesc;
/* Find a LockDesc -- useful below */ /* Find a LockUsageDesc -- useful below */
LockDesc &getLockDesc(TicketLock &criterionLock) LockUsageDesc &getLockUsageDesc(Qutex &criterionLock)
{ {
for (auto &reqLock: requiredLocks) { for (auto &reqLock: requiredLocks) {
if (reqLock.first == &criterionLock) { return reqLock; } if (reqLock.first == &criterionLock) { return reqLock; }
@@ -235,7 +237,7 @@ LockSet::release()
} }
``` ```
Now, the TicketLock class is what we'll use for synchronization. It's just a Now, the Qutex class is what we'll use for synchronization. It's just a
combination of 2 atomic<bool> and a std::list. combination of 2 atomic<bool> and a std::list.
``` ```
@@ -250,24 +252,24 @@ class SpinLock
class LockSet class LockSet
{ {
/* Modify the std::vector of SpinLock to instead be: /* Modify the std::vector of SpinLock to instead be:
* std::vector<LockDesc> locks; * std::vector<LockUsageDesc> locks;
*/ */
std::vector<LockDesc> locks; std::vector<LockUsageDesc> locks;
} }
class TicketLock class Qutex
{ {
public: public:
std::list<LockerAndInvoker>::iterator register( typedef std::list<LockerAndInvoker> LockerAndInvokerList;
const LockerAndInvoker &lockvoker
) LockerAndInvokerList::iterator register(const LockerAndInvoker &lockvoker)
{ {
/** EXPLANATION: /** EXPLANATION:
* Just insert the lockvoker into the rear of the list. * Just insert the lockvoker into the rear of the list.
* *
* Then, since we want to store the * Then, since we want to store the
*/ */
std::list<LockerAndInvoker>::iterator it; LockerAndInvokerList::iterator it;
lock.acquire(); lock.acquire();
queue.push_back(lockvoker); queue.push_back(lockvoker);
@@ -278,7 +280,7 @@ public:
return it; return it;
} }
void unregister(std::list<LockerAndInvoker>::iterator it) void unregister(LockerAndInvokerList::iterator it)
{ {
lock.acquire(); lock.acquire();
queue.erase(it); queue.erase(it);
@@ -386,10 +388,10 @@ public:
* If queue.size==3 and LockSet.size()==5, then just * If queue.size==3 and LockSet.size()==5, then just
* push_back(failedAcquirer). * push_back(failedAcquirer).
* *
* It is impossible for a TicketLock queue to have only one * It is impossible for a Qutex queue to have only one
* item in it, yet for that Lockvoker item to have failed to * item in it, yet for that Lockvoker item to have failed to
* acquire the ticketLock. Being the only item in the ticketQ * acquire the Qutex. Being the only item in the ticketQ
* means that you must succeed at acquiring the TicketLock. * means that you must succeed at acquiring the Qutex.
*/ */
int swapPosition = min( int swapPosition = min(
queue.size(), queue.size(),
@@ -405,12 +407,12 @@ public:
* *
* Consider 2 different locks with 2 different items in them * Consider 2 different locks with 2 different items in them
* each, both of which come from 2 particular requests: * each, both of which come from 2 particular requests:
* TicketLock1: Lockvoker1, Lv2 * Qutex1: Lockvoker1, Lv2
* TicketLock2: Lv2, Lv1 * Qutex2: Lv2, Lv1
* *
* Moreover, both of these lockvokers have requiredLocks.size()==2, * Moreover, both of these lockvokers have requiredLocks.size()==2,
* and the particular 2 locks that each one requires are indeed * and the particular 2 locks that each one requires are indeed
* TicketLock1 and TicketLock2. * Qutex1 and Qutex2.
* *
* This particular setup basically means that in TL1's queue, Lv1 * This particular setup basically means that in TL1's queue, Lv1
* will wakeup since it's at the front of TL1. It'll successfully * will wakeup since it's at the front of TL1. It'll successfully
@@ -432,9 +434,9 @@ public:
* *
* This state of affairs is stable and will persist unless these * This state of affairs is stable and will persist unless these
* queues are reordered in some way. Hence: that's why we rotate the * queues are reordered in some way. Hence: that's why we rotate the
* items in a TicketLockQ after backing off of it. Backing off means * items in a QutexQ after backing off of it. Backing off means
* Not necessarily that the calling LockVoker failed to acquire * Not necessarily that the calling LockVoker failed to acquire
* THIS PARTICULAR TicketLock, but rather than it failed to acquire * THIS PARTICULAR Qutex, but rather than it failed to acquire
* ALL of its required locks. * ALL of its required locks.
* *
* Hence, if we are backing out, we should also rotate the items * Hence, if we are backing out, we should also rotate the items
@@ -466,7 +468,7 @@ public:
* the prev owner was the previous front item; or whether we should * the prev owner was the previous front item; or whether we should
* always wake up the new front item. * always wake up the new front item.
* *
* Recall that because a sequence can acquire a ticketLock without being * Recall that because a sequence can acquire a Qutex without being
* at the front of the queue (because it could merely be in the top X% * at the front of the queue (because it could merely be in the top X%
* of items instead), this means that during a call to release(), the * of items instead), this means that during a call to release(), the
* owning async sequence may not be at the front -- it needs only be in * owning async sequence may not be at the front -- it needs only be in
@@ -513,6 +515,6 @@ public:
public: public:
SpinLock lock; SpinLock lock;
std::atomic<bool> isOwned; std::atomic<bool> isOwned;
std::list<LockerAndInvoker> queue; LockerAndInvokerList queue;
}; };
``` ```