ExecutionManager (variable scope in runnable)

Hi @pturmel,

Sorry If it was a very trivial question but I don’t understand my mistake in this context.
As you can see below, In my module development I have multiple instance of this abstract ‘Sample’ class.
For each instance, I register my runnable ‘TimeoutManager’ with an uniqueID with an initial delay.
Before the runnable execution, I update an atomic Long with ‘doSomething()’ function. Unfortunately when my runnable ‘TimeoutManager’ run the atomicLong is stay with the initial Value.
The execution manager don’t take the context (variables) during execution runnable.
How can I have the right value of my AtomicLong during TimeoutManager.run()?

import com.inductiveautomation.ignition.common.execution.ExecutionManager;
import com.inductiveautomation.ignition.gateway.model.GatewayContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public abstract class Sample{

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final ExecutionManager execm;
    private final TimeoutManager timeoutManager = new TimeoutManager();
    private AtomicLong myLastAccessTime = new AtomicLong(System.currentTimeMillis());


    public Sample(GatewayContext _context){
        this.execm = _context.getExecutionManager();
    }

    public void registerRun() {
        execm.registerWithInitialDelay("UUID", TimeoutManager.class.getName(), timeoutManager, 30000, TimeUnit.MILLISECONDS, 10000);
logger.debug("registerRun()");
    }

    public void unRegisterRun() {
        execm.unRegister("UUID",TimeoutManager.class.getName());

    }

    public void doSomething(){
        //Do something Here
        myLastAccessTime.set(System.currentTimeMillis());
logger.debug("doSomething() > LastAccessTime:[{}]",getLastAccessTime());
    }

    public Long getLastAccessTime(){
        return myLastAccessTime.get();
    }

    private class TimeoutManager implements Runnable{

    public TimeoutManager(){
 logger.debug("TimeoutManager > LastAccessTime:{}",getLastAccessTime());
}
        @Override
        public void run() {
            long currentTime = System.currentTimeMillis();
            long lastCommTime = getLastAccessTime();

            if ((currentTime - lastCommTime)> 30000){
                logger.debug("TimeoutManager.run()> You haven't done Something()  is in timeout Delay:[{}]ms LastAccessTime:[{}]",(currentTime-lastCommTime),lastCommTime);
            } else {
                logger.debug("TimeoutManager.run()> You have done Something");
         }
        }
    }
}
registerRun()
TimeoutManager > LastAccessTime:1507275293767
doSomething() > LastAccessTime:[1507275293867]
doSomething() > LastAccessTime:[1507275293892]
TimeoutManager.run()> You haven't done Something()  is in timeout Delay:[30000]ms LastAccessTime:[1507275293767]

Thanks.

Not entirely sure. But look at “Delay:[30]ms” in your output. That suggests that the initial delay didn’t work as advertised.

Sorry I correct my Sample class example to illustrate the case

Hmm. I still don’t see any obvious problem. Consider using a volatile long instead of an AtomicLong – you only have one writer, the doSomething method, and replacing the value of a volatile long is guaranteed to be atomic in Java. That chapter of the Java spec discusses a number of gotcha’s that might be involved.

The code sample you present looks fine… I suspect the problem is in the context surrounding how you’re using it.

Do you have more than one instance of Sample and are you calling doSomething() on a different one than you think?

Another thing I find strange, your logs have these messages:

registerRun()
TimeoutManager > LastAccessTime:1507275293767

Given the code you’ve supplied, that order should be reversed, or there’s more than one instance logging.

I try your volatile suggestion but it s still the same issue.

Interesting suggestions. I don’t systematically uninstall my module between each test on my plateform. The context is maybe wrong.

Finally, there will have more than one instance of sample class. (The original code are here: https://github.com/IgnitionModuleDevelopmentCommunity/OpcUaFctAddon/blob/master/OpcUaFctAddon-gateway/src/main/java/com/bouyguesenergiesservices/opcuafctaddon/gateway/fct/GatewayFct.java)

I will made more tests on monday!

Thank you @Kevin.Herron.

My issue was that I create more than one instance with a quasi similar UUID (In logs viewer there is just 1 digit who changed ). I will doSomething() in one and check in an other if there is a Timeout.

Moreover as @pturmel said, I add AtomicLong consideration in my code implementation.

As usual, It was an efficient intervention. Thanks @Kevin.Herron and @pturmel.

1 Like