TelluIoT / ThingML

The ThingML modelling language
https://github.com/TelluIoT/ThingML
Apache License 2.0
102 stars 33 forks source link

Properly canceling timers? #157

Open jakhog opened 7 years ago

jakhog commented 7 years ago

Just a thought I had while writing some code with timer-timeouts.

At least the way the Timer protocol is implemented in C right now, you might encounter a situation where - while handling a message - you cancel a timer that has already enqueued a timeout message in the message queue. This will not remove the already enqueued timeout message.

Imagine the following desired behavior: you want to wait a few seconds after a button is pressed before you do something more. Using timers, this could be accomplished with the following pseudo-ThingML code:

thing MyThing
{
    message start_timer(id, time);
    message cancel_timer(id);
    message timeout(id);
    required port clock
    {
        sends start_timer, cancel_timer
        receives timeout
    }

    message pressed();
    required port button
    {
        receives pressed
    }

    statechart MyStates init Waiting
    {
        state Waiting
        {
            on entry clock!start_timer(0, 1000)

            internal event button?pressed action do
                clock!cancel_timer(0)
                clock!start_timer(0, 1000)
            end

            transition -> DoSomething clock?timeout
        }
        state DoSomething
        {
            ...
        }
    }
}

If you are very unlucky and the button just before a timeout, this would result in the timeout message still being processed immediately after the button press.

Fixing this non-intuitive behavior might include some not-so-pretty fixes either removing timeout messages from the message queue, or only adding timeout messages if it is completely empty. I don't really like any of them, but still feel like we should guarantee that this kind of behavior does not happen when using the timers.

Do you have any thoughts or other suggestions for fixes @ffleurey @brice-morin ?

brice-morin commented 7 years ago

IMHO, as long as timers are components (or protocols), the behavior you describe may be problematic, but completely normal. I do not think we should allow messing with FIFOs.

But we could make time/timers a concept in ThingML, and there we can systematically generate whatever is needed, and not make exceptions for this and that component/protocol. But I guess this is quite an endeavor... like CEP ;-) (though it might help with CEP v2 to have time/timers in the language).

@ffleurey ?

nharrand commented 7 years ago

You could also give unique id to timeout messages(by incrementing a var) and keep a register of the last canceled id, and then check upon timeout reception that the id isn't superior to the register.