B4J Question Delegating semiphore-like access to hardware?

techknight

Well-Known Member
Licensed User
I have a peripheral that is plugged into my Raspberry Pi via GPIO. Works great. However there is a caveat.

The peripheral can only process one thing at a time. (has a FIFO, and interrupt).

This works fine except with MQTT, its asyncronous so what happens is if a command comes in at "just" the right time, it can interrupt another routine or reenter the already running routine thats using the peripheral and this causes a crash with the peripheral becuase now something got injected in between something else.

So I need some way to delegate access to the peripheral so that only one thing at a time can access it, but, at the same time, no requests are lost. This is where I am getting confused and running into problems.

I could simply do InUse = True or False. But, this doesn't work because of 1) A race condition can occur if multiple subs are wanting access and waiting/sleeping, and 2) if something is already using it, it could lose the request because if its in-use already, it wont process.

I could use a wait for InUse = true, but if another call comes in while on top of that call, I cant "stack up" the data/requests for the use of peripheral.

Any ideas? Thanks.
 

techknight

Well-Known Member
Licensed User
While MQTT communication is asynchronous, the event, like all other events, runs on the main thread. It will not interrupt other code that is currently running.

You certain about that? I have had a very different experience so far.

if an MQTT packet arrives when the system is doing nothing, it begins executing the code which handles the message and passes it along to the routine that operates the peripheral. But if the routine operating the peripheral is running, the MQTT message handler can fire again. and interrupts the routine running the peripheral to run another command which also uses the peripheral. So what I end up with is this:

(part of message 1)(Message 2)(remaining part of message 1) going to the peripheral.

Now there are several "Wait For" statements in all those subroutines because I have to Wait For the peripheral to become ready, or a response back from the peripheral. So its these Wait For statements that get caught and allow the MQTT handler to run again.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
You certain about that?
Yes.
However if you are using Wait For or Sleep in your code then it is likely to happen before the other code "completes".

Implement a queue:
B4X:
Sub StartQueueHandler
 Do While True
   If Queue.Size > 0 Then
     Dim q As YourTypeWithAllDataNeeded = Queue.Get(0)
      Queue.RemoveAt(0)
     Wait For (DoSomething(q)) Complete (Unused As Boolean)
 End If
 Sleep(100)
 Loop
End Sub

Whenever there is a new task, create a YourTypeWithAllDataNeeded object and add it to Queue.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Now thats a nice solution! I just have to figure out how to get a return code, so the subroutine that stacks up on the Queue knows it has passed or failed.

Is Queue a list? or Map?
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
List
 
Upvote 0
Top