Inter-piston state communication / Cancellation tokens / Semaphores


#1

1) Give a description of the problem

According to the documentation, pistons take a local copy of global variables when they execute, thus the global variables become local variables. I’ve been trying to use global variable for “inter-piston communication”. I want to tell them all to cancel based on a signal from one of the others.

I’ve been trying to use a local variable “WakeUpCancelled” to signal to all the other pistons that the wake up process has been cancelled and that they should all terminate. Obviously it doesn’t work because the global variable is a local one for each piston.

How can I use some kind of semaphore to indicate to other running pistons that they should halt their execution?


#2

I would suggest creating small pistons to demonstrate the issue then post the green snapshots so we can import it and try it to better understand the issue. I like pictures :grin:


#3

Here is a very simple example… a master piston that calls two different, but identical pistons.

These two pistons have a for loop which waits a random amount of time. I want the first piston that reaches 50 to cancel itself and the other one.


#4

You could use a virtual switch, although it’s slightly messy as it leaves a device around which you never really want to see or use on its own.


#5

A few thoughts come to mind…

  • I would add a small WAIT in between the “execute pistons”…
  • In the other pistons, line 17 should be at least “step 1” (if you want it to advance)
  • I would likely change lines 27 to say “is greater than 50”… (Just in case of spam)
  • (optional) Instead of using $index, I prefer using a local integer variable called “i” instead. This lets me actually SEE the progression at any time.

#6

Yeah sorry the step 0 is an error. I appreciate the input but these aren’t real pistons they’re just simple examples I threw together. My actual pistons do NOTHING like any of this.

I need advice about how to use a semaphore of some kind. Some kind of shared state they both have access to like a cancellation token or semaphore.


#7

I’ve thought about a virtual switch - but I agree its messy. Surely there must be a better way.


#8

If you want pertinent advice, it helps to see your basic structure…


I try my best to avoid semaphores… You may be the first person actually seeking them.


In my experience, SimSwitches are awesome… but your @global condition should work as well. (as long as you don’t expect an instant abort… it might take 10 seconds)


#9

The actual code logic is pretty complex. I’ve trimmed it down to the simplest form to show my problem: Two long-running pistons that I want to be able to send a cancellation signal to.

Semaphores are the standard way of sending signals between different threads in concurrent programming. They can be used in many different ways such as trigging start, stop, release, notify or wait. In my case I want to send a signal to terminate.

Global variables don’t work, because each piston takes a snapshot of the global variable when the piston starts; specifically to AVOID it changing while the piston is executing.
https://wiki.webcore.co/Variable#Global_Variables

And no… Simswitches are not awesome for this use-case. They’re visible to SmartThings and even detected by Alexa. The solution should be something that is constrained to this piece of programming, not a global device available to my entire smarthome ecosystem


#10

Then I reference my earlier suggestions.


I would not apply that logic here in webCoRE. I think of them like an:
Ooops, something doesn’t seem quite right… Let’s try again” …

Definitely not desirable or any logic I want to base a piston around.


This is true, but a @global also updates each time there is a WAIT longer than 9 seconds. (achieved via your random())


Yup, but you can name them anything, so if the first letter is the letter “Z”, it bumps it to the bottom of every list… Out of the way.

And the likelihood that you can pronounce the nonsense word to Alexa is quiet slim.


I agree. Without knowing your full setup here. the generic advice is to not use a SimSwitch in this case…

I’d probably process using a local variable, and copy it to a @global at each loop…


#11

It is worth noting that if the piston encounters a wait statement lasting more than five seconds (and in certain cases shorter ones) it will exit, thus causing any changes to globals to be written out, and when it wakes up it will cache the globals again.

Also you can subscribe to changes in globals, which your sample pistons do.