Manage the number of active worker threads.
The ThreadGate limits the number of threads that are simultaneously
active in order to implement adaptive rate control.
Initially the ThreadGate allows only one thread to be active. For
each successful work item, another thread is activated and for each
failed item, the number of active threads is reduced by one. When only
one thread is active, failures will cause exponential backoff.
For example, a ThreadGate instance, thread_gate can be used in a number
of threads as so:
# Block until this thread is enabled for work.
thread_gate.StartWork()
try:
status = DoSomeWorkInvolvingLimitedSharedResources()
succeeded = IsStatusGood(status)
badly_failed = IsStatusVeryBad(status)
finally:
if succeeded:
# Succeeded, add more simultaneously enabled threads to the task.
thread_gate.FinishWork(instruction=ThreadGate.INCREASE)
elif badly_failed:
# Failed, or succeeded but with high resource load, reduce number of
# workers.
thread_gate.FinishWork(instruction=ThreadGate.DECREASE)
else:
# We succeeded, but don't want to add more workers to the task.
thread_gate.FinishWork(instruction=ThreadGate.HOLD)
the thread_gate will enable and disable/backoff threads in response to
resource load conditions.
StartWork can block indefinitely. FinishWork, while not
lock-free, should never block absent a demonic scheduler.