Docs: Qutex updated notes -- still WIP
This commit is contained in:
+24
-22
@@ -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;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
Reference in New Issue
Block a user