coroutines-like sequential processing (Semaphore usage)

Share your advanced PureBasic knowledge/code with the community.
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

coroutines-like sequential processing (Semaphore usage)

Post by fsw »

Some programs depend on a sequential flow in order to work as intended.
Coroutine-like functionality can help with that.

Code: Select all

Global ProducerSemaphore = CreateSemaphore()
Global ConsumerSemaphore = CreateSemaphore()
Global Mutex             = CreateMutex()
Global Task.s

Procedure Producer(Total)

  For i = 1 To Total
    ; producer task mutex lock to be thread-safe
    LockMutex(Mutex)
      Task = "bake bread"
      PrintN(Task)
    UnlockMutex(Mutex)   

    ; signal that there is a new task done
    SignalSemaphore(ProducerSemaphore)
    ; wait for the consumer to consume
    WaitSemaphore(ConsumerSemaphore)
  Next i
   
EndProcedure

 
Procedure Consumer(Total)
  For i = 1 To Total 
    ; wait for the producer to produce
    WaitSemaphore(ProducerSemaphore)
   
    ; consumer task mutex lock to be thread-safe
    LockMutex(Mutex)
      Task = "eat bread"
      PrintN(Task)
    UnlockMutex(Mutex)

    ; signal that there is a new task done
    SignalSemaphore(ConsumerSemaphore)
  Next i
EndProcedure

; main
OpenConsole("Coroutines-like sequential process")

If CreateThread(@Producer(), 30)
  CreateThread(@Consumer(), 30)
EndIf

Input()

CloseConsole()
:idea:

EDIT: changed thread title, changed queue with a normal variable so the reader can focus at the task at hand, exchanged typos with other typos
Thank you Freak :wink:
Last edited by fsw on Fri Mar 01, 2013 12:56 am, edited 10 times in total.

I am to provide the public with beneficial shocks.
Alfred Hitshock
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Semaphore usage

Post by freak »

What you effectively did is limit the queue size to 1 because the producer now waits for the queue to be empty before adding another element. What is the purpose of the queue then? There is no parallel execution anymore because one thread is always waiting. Why even use threads then?

The delay is just in the example to simulate work that the producer does. Its not there to serialize the output. In fact, try adding a delay to the consumer part to simulate work there, and you will see that the producer now sits around waiting for the consumer to finish before producing more elements. That is not a good CPU utilization either.

If you want to use the available resources best then use the original example. There if the producer is faster than the consumer, the items queue up (but still arrive in order. notice how the 1st queue element is also sequential if you remove the delay). Then if the consumer is faster for a while it will catch up. The only actual wait condition is if the consumer is much faster than the producer (as simulated by the delay). In this case waiting is the only possibility because there is no work to do.
quidquid Latine dictum sit altum videtur
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: coroutines-like sequential processing (Semaphore usage)

Post by fsw »

Maybe you did not understand what I tried to accomplish.
You focused on the Queue which through you off from what I wanted to show.

I tried to show how coroutines-like sequential processing can be done.

Coroutines are different than threads.
Coroutines wait for other buddy-coroutines to finish their task.

I will change the thread name to: "coroutines-like sequential processing"
I will also exchange the queue with a string variable in the first post.

Thank you Freak :wink:

I am to provide the public with beneficial shocks.
Alfred Hitshock
Post Reply