Using Swift and semaphores to illustrate a serialization approach:
Given: a class with the asynchronous run method that will run on several objects at the same time, and the goal is to prevent each of them from starting until it finishes.
The problem is that the run method allocates a lot of memory and uses a lot of system resources, which can cause a lack of memory, among other problems, if too many are started at the same time.
The idea is this: if you use a sequential queue, only one will work at a time, one after another.
Create a sequential queue in global space by class:
let serialGeneratorQueue: DispatchQueue = DispatchQueue(label: "com.limit-point.serialGeneratorQueue", autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem) class Generator { func run() { asynchronous_method() } func start() { serialGeneratorQueue.async { self.run() } } func completed() {
The 'run method of this class, for which a lot of objects will be created and launched, will be processed in a sequential queue:
serialGeneratorQueue.async { self.run() }
In this case, autoreleaseFrequency is the .workItem to clear the memory after each run.
The run method has some general form:
func run() { asynchronous_method() }
The problem is this: the run method ends before the asynchronous_method completes, the next run method in the queue starts, etc. Thus, the goal is not achieved, since each asynchronous_method is executed in parallel, and not sequentially.
Use the semaphore to fix it. In class declare
let running = DispatchSemaphore(value: 0)
Now asynchronous_method shuts down, calls the method: complete:
func completed() {
A semaphore can be used to serialize a chain of asynchronous methods by adding 'running.wait () to the' run method:
func run() { asynchronous_method() running.wait() }
And then in the complete () method add 'running.signal ()
func completed() {
The running.wait () function in 'run will prevent it from exiting until the signal is completed by the completed method using running.signal (), which in turn prevents the sequential queue from starting the next run method in the queue. Thus, the chain of asynchronous methods will indeed be executed sequentially.
So, now the class has the form:
class Generator { let running = DispatchSemaphore(value: 0) func run() { asynchronous_method() running.wait() } func start() { serialGeneratorQueue.async { self.run() } } func completed() {