Files
hayodea b7cf4c9135 Docs: Document the locking mechanism we plan to use
This new locking mechanism is very cumbersome, but highly
throughput maximizing. It trades high memory usage to gain
high throughput.

We may end up even being able to get the high throughput
without incurring the high memory usage by using std::bind
objects, etc.
2025-09-10 18:14:20 -04:00

1.9 KiB

Spinqueueing: A new locking method that only blocks requests and not threads.

The idea is that instead of using sleeplocks like mutexes, we instead only spin particular request objects by re-posting them to the queue.

Particular requests may need a given shared resource. Instead of sleeping a whole thread while that particular request waits for the resource, we instead sleep the request itself by re-posting it into the thread's queue. This basically implements a kind of spinlock without busy-waiting. The underlying thread is never blocked unless it has no requests that can make forward progress.

Forward progress through requests is only halted when an external resource is actually being waited on. Generally this will be an actual hardware event that is being waited on. No software bottlenecks will be slept on.

All locks in the program are simple spinlocks, but the algorithm to spin on them is:

Each async call has a "locker and invoker":

int funcThatCallsAnAsyncFunc(...) { // Do preparatory stuff ...

// Post the lockvoker to the target thread.
targetThread.io_service.post(
	[targetThread, /* args to asyncOperationReq captured here */]()
	{
		int nAcquired;
		for (nAcquired=0; nAcquired<nLocksRequired; nAcquired++)
		{
			if (!requiredLocks->tryAcquire()) {
				break;
			}
		}
		if (nAcquired < nLocksRequired)
		{
			for (int i=0; i<nAcquired; i++) {
				requiredLocks->release();
			}

			/* Unsure how to recapture the lambda object and re-enqueue it.
			 * Dunno if that's even possible. But this is the essence of the
			 * queue-spin system. We re-enqueue the lockvoker until it
			 * gets all locks required. Then it will invoke the async
			 * frontend.
			 */
			targetThead.io_service.post(this?);
		}

		managerObject.asyncOperationReq(
			/* args to asyncOperationReq passed here */);
	}
);

}

Idk how to encapsulate lockvokers into a terse, reusable idiom.