I'm trying to build an intuition for how expensive a single task cancellation check is. My ultimate goal is to get (or write myself) some guidance on how often a computation-intensive function should perform manual cancellation checks to be a good concurrency citizen.
I started by writing a benchmark, but I'm not yet confident enough in the results (i.e. my benchmarking method) to trust or share them.
Next, I looked at the implementation of static var Task.isCancelled in the standard library to get an idea of the potentially expensive operations. From what I gathered, static var Task.isCancelled effectively performs these steps:
- Get a pointer to the current task object from thread-local storage
- Retain the task object (= an atomic write to the refcount field?)
- Perform an atomic read (ordering:
std::memory_order_relaxed) on the task object's status field to get the cancellation status.
To people familiar with the implementation, is this sequence correct or did I miss something?
Even if I can't assign some fixed "cost" to the operations listed above, I find it helpful to know what happens under the hood because it allows me to compare the cost of the cancellation check to the cost of my actual code.