I've been developing my own PING/PONG for a websocket application and needed to manage the state of whether PONG has been received.
To make sure I don't accidentally change the variable and to avoid name collisions I've encapsulated the variable into get and set methods and made funny changes to make sure it'll not be accidentally changed by other parts of the code.
The main methods I use to modify and access the state is as follows.
void setReceivedPongToFalse() {
if (enableLogging) log.debug "setReceivedPongToFalse()"
state.elephant = "FALSE STRING"
if (enableLogging) log.debug "receivedPong set to: ${state.elephant}"
}
void setReceivedPongToTrue() {
if (enableLogging) log.debug "setReceivedPongToTrue()"
state.elephant = "TRUE STRING"
if (enableLogging) log.debug "receivedPong set to: ${state.elephant}"
}
boolean getReceivedPong() {
if (enableLogging) log.debug "getReceivedPong(): ${state.elephant}"
return state.elephant == "TRUE STRING"
}
However, in my logs, for some reason the variable was set to false after it was set to true. Could the be caused by some race conditions of event processing? Is there a thread safe way to modify state?
For my own curiosity.... Would that mean any comm's sent to the app would potentially require some kind of wait for the platform while the app deals with the call / data being processed from a previous call?
By method, do you mean the high level commands defined in my device or functions like
void setReceivedPongToTrue() {
if (enableLogging) log.debug "setReceivedPongToTrue()"
state.elephant = "TRUE STRING"
if (enableLogging) log.debug "receivedPong set to: ${state.elephant}"
}
The former is true since the chain of function calls are triggered through a cron scheduled call to ping in installed().
I only glanced at the methods you excerpted in your post.
But you set state.elephant and then immediately print its value to the log. I think you are saying that the print doesn't match the value you set it to. Correct? If so, sounds like a caching issue to me.
Thanks for the suggestion. I wonder if there is any difference between using @Field vs state? I tried using a regular HashMap and a ConcurrentHashMap and both worked fine. Yet using state doesn't work.
@bravenel, one thing I've discovered is that while you can use state and atomicState to hold non-simple data types (like maps or lists), you cannot manipulate them directly. For example:
atomicState.myMap = new HashMap()
atomicState.myMap.put("myKey", "myVal")
log.debug "myMap = ${atomicState.myMap}" // will be an empty map!!
tmap = atomicState.myMap
tmap.put("myKey", "myVal")
atomicState.myMap = tmap
log.debug "myMap = ${atomicState.myMap}" // will be as expected