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.
```
/* We'll need to rename current class LockSpec to LockSet. */
class LockSet
{
/* 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
* definition dependencies.
*/
typedef std::pair<TicketLock, LockDesc> LockDesc;
typedef std::pair<Qutex, LockerAndInvokerList::iterator>
LockUsageDesc;
/* Find a LockDesc -- useful below */
LockDesc &getLockDesc(TicketLock &criterionLock)
/* Find a LockUsageDesc -- useful below */
LockUsageDesc &getLockUsageDesc(Qutex &criterionLock)
{
for (auto &reqLock: requiredLocks) {
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.
```
@@ -250,24 +252,24 @@ class SpinLock
class LockSet
{
/* 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:
std::list<LockerAndInvoker>::iterator register(
const LockerAndInvoker &lockvoker
)
typedef std::list<LockerAndInvoker> LockerAndInvokerList;
LockerAndInvokerList::iterator register(const LockerAndInvoker &lockvoker)
{
/** EXPLANATION:
* Just insert the lockvoker into the rear of the list.
*
* Then, since we want to store the
*/
std::list<LockerAndInvoker>::iterator it;
LockerAndInvokerList::iterator it;
lock.acquire();
queue.push_back(lockvoker);
@@ -278,7 +280,7 @@ public:
return it;
}
void unregister(std::list<LockerAndInvoker>::iterator it)
void unregister(LockerAndInvokerList::iterator it)
{
lock.acquire();
queue.erase(it);
@@ -386,10 +388,10 @@ public:
* If queue.size==3 and LockSet.size()==5, then just
* 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
* acquire the ticketLock. Being the only item in the ticketQ
* means that you must succeed at acquiring the TicketLock.
* acquire the Qutex. Being the only item in the ticketQ
* means that you must succeed at acquiring the Qutex.
*/
int swapPosition = min(
queue.size(),
@@ -405,12 +407,12 @@ public:
*
* Consider 2 different locks with 2 different items in them
* each, both of which come from 2 particular requests:
* TicketLock1: Lockvoker1, Lv2
* TicketLock2: Lv2, Lv1
* Qutex1: Lockvoker1, Lv2
* Qutex2: Lv2, Lv1
*
* Moreover, both of these lockvokers have requiredLocks.size()==2,
* 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
* 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
* 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
* 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.
*
* 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
* 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%
* 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
@@ -513,6 +515,6 @@ public:
public:
SpinLock lock;
std::atomic<bool> isOwned;
std::list<LockerAndInvoker> queue;
LockerAndInvokerList queue;
};
```