Homey Community Forum

[APP] Semaphore

Introduction

Disclaimer: this app is for advanced usage of Homey! For basic home automations you propably don’t need this

Concurrency is the ability to run different applications in parallel and handle resources appropriately. Homey for example allows you to run multiple flows at once but it does not ensure that a specific resource (i.e. a logic variable) is accessed only once at a time. This can be problematic and can cause so named racing conditions.
A semaphore is a well known principle to prevent such issues as they ensure a resource is accessed only once at a time. This app provides such an semaphore for your Homey and enables more powerful automations.

Get it over here!

Example

Let’s consider the following scenario: you have 3 flows that all get triggered by the same event (i.e. a button press). Furthermore there is an logic variable initialized with the value of 0. Let’s assume that every flow will calculate the value of the variable as +=1. As result you would expect the variable to be 3 after all the flows have completed, but in reality you will find that it has always a different value!
The reason for that is that we have a racing condition here. The operation of getting the variable, increasing it and writing it back to the memory is not atomic. Therefore it can be that multiple flows operate on the same variable at the same time. For example you would have this:

  1. flow 1 reads the variable into the memory (0)
  2. flow 2 reads the variable into the memory (0)
  3. flow 1 increase the value and writes the variable back to memory (1)
  4. flow 2 increase the value and writes the variable back to memory (1)

To prevent this behaviour we need to ensure that only one flow at the time is reading the variable, increasing it and writing it back.

To do so we need a semaphore:

  1. in the condition of the 3 flows add the ‘Wait until the semaphore is unlocked’ flow card
  2. in the action of the 3 flows add the ‘Unlock the semaphore’ flow card after the calculation

Now the following will happen:

  1. the first flow that checks the condition will lock the semaphore
  2. whenever one of the other flows comes to check the condition it will wait and not continue for the moment (usually we are talking about milliseconds here)
  3. the first flow card will do it’s calculation and once this is done it will unlock the semaphore
  4. the next flow card that is waiting can now continue etc. until all work is done!
4 Likes

reserved

reserved too

reserved as well

Maybe a stupid question, but does the semaphore lock one specific variable or all variables or how the semaphore is configured what to lock. Couldn’t get the app to install yet and eager to test.

Hey,

The semaphore does not lock at a specific variable and it is also not tied to a variable at all. You can just ensure that while you lock the semaphore that no other flow enters this “critical” section. Currently there is also just one sempaphore at the time.

Regarding the installation issue: are you using homey v4.x?

Interesting idea :smiley: One question: if you release the semaphore in an action card, and action cards are started concurrently (as they are), how can you ensure that the calculation is protected by the semaphore? It seems to me there’s still a race condition between the semaphore being released and the calculation finishing.

I’d also be interested to learn how the semaphore in implemented in the app :slight_smile:

3 Likes

I guess, in the example, the unlock semaphore would have to be moved to a new flow triggered by the variable update.

Yep I’m using the 4.xx firmware. So it’s only available to 5.0?

Still interesting app and have to say “out of the ordinary” idea. I never thought this could be possible in an app, but only in Homey “core functions”. Have to wait for the stable 5.0 release to test it.

Presently I only have an issue with multiple zwave or zigbee actions running concurrently. I have solved this in the past with wait times (e.g. first action with 0 delay, second action with 1 second delay etc.).

I still have hopes that the concurrent activity issue on zwave and zigbee is solved with V5.0 of the firmware.

I’ll be sure to check out your semaphore should v5 nog solve my issues.

Thanks for the good work in advance!!

Good question;) My basic idea was the following:

  1. there is a global “locked” variable in the app. This is one is not specially guarded for concurrency but it can only be changed with the flow cards
  2. all code that changes the value of this variable is protected against racing conditions by a third party library.
  3. the condition card checks the value of the locked variable (protected code). If it is unlocked we lock it and continue. Otherwise we leave the critical path and wait and try again later.
1 Like

Yes and no;) It actually should be working for 4.x too but there is a bug in homey wich is solved in v5.0. Actually I thought it should work on v4.x but if this is really not the case I’ll update the app

I don’t think that bug is ‘solved in V5’. The fix is the latest CLI tells you about the problem and fails validation, so you are made aware of the problem in your code so that you can fix it.

What Robert was talking about is all the cards in the Then section are run concurrently. So there is no guarantee that the calculation has finished when the Unlock semaphore card is run.

1 Like

Yes, that would be a good solution :+1:t2:

1 Like

I wasn’t aware of that, but yes you’ re right, this needs to be solved by a second flow. I’ll update the example