tinyosnesc

TinyOS event return type meaning


So in TinyOS an interface is composed of commands and events. When a module uses an interface, it calls its commands and provides an implementation of its events (provides an event handler).

The sense of the return type of a command is clear, it is the same as that of any function/method in any programming language, but, the return type of an event results unclear to me.

Let's take an example:

interface Counter{
    command int64_t getCounter(int64_t destinationId);
    event int64_t counterSent(int64_t destinationId);
}

Let's define a module that provides the Counter interface.

module Provider{
    provides interface Counter;
}

implementation {
    int64_t counter;
    counter = 75; //Random number

    /** 
    Returns the value of the counter and signals an event that
    someone with id equal to destinationId asked for the counter. 
    **/

    command int64_t getCounter(int64_t destinationId){
        int64_t signalReturnedValue;
        signalReturnedValue = signal counterSent(destinationId);
        return counter;
    }
}

Now let's define two module which use this interface.

module EvenIDChecker{
    uses interface Counter;
}
implementation{
    /**
    Returns 1 if the destinationId is even, 0 otherwise
    **/

    event int64_t counterSent(int64_t destinationId){
        if(destinationId % 2 == 0){
            return 1;
        } else {
            return 0;
        }
    }
}

Now let's define another module which uses the same interface but does the inverse of the EvenIDChecker module.

module OddIDChecker{
    uses interface Counter;
}
implementation{
    /**
    Returns 1 if the destinationId is odd, 0 otherwise
    **/

    event int64_t counterSent(int64_t destinationId){
        if(destinationId % 2 == 1){
            return 1;
        } else {
            return 0;
        }
    }
}

In the end, what would be the final value of the var signalReturnedValue?


Solution

  • The value is unspecified or this code may even not compile.

    In TinyOS, there's a concept of combine functions, which are of signature type f(type, type) and their purpose is to reasonably combine two values of the same type. For error_t there's such a function defined:

    error_t ecombine(error_t e1, error_t e2) {
      return (e1 == e2) ? e1 : FAIL;
    }
    

    Combine function is called automatically in a situation such as in your code snippet.

    If you want to define a combine function in this example, you need to typedef the return type of the event. See 4.4.3 Combine Functions for more information.

    Note that the situation is symmetric for commands. You can wire two implementations of an interface to a single uses declaration like this:

    configuration ExampleC {
      ExampleP.Counter -> Counter1;
      ExampleP.Counter -> Counter2;
    }
    

    Assuming that Counter has a command that returns something, whenever ExampleP calls that command, two implementations are executed and two return values are combined.