Skip to content

AndroidTimerModel

vasilakis edited this page Apr 21, 2011 · 6 revisions

There are a lot of times, especially on routing or zeroconf applications, when you need to schedule some functions callbacks. In wiselib, function callbacks are implemented with the delegates written by Sergey Ryazanov. Delegates is a mechanism in C++ that enables us to use true object-oriented member function pointers. This is really usefull since they can be used anywhere you would use a function pointer in a C program. On the other hand the timer has been implemented using setitimer system call. When the interval timer of setitimer is expired a SIGALRM signal is sent. Remember that unless you disable any debugging features android offers no SIGALRM will be caught by signalHandler of AndroidTimerModel class. What AndroidTimerModel offers you is an internal implementation of callbacks and timers and give you an abstract layer. There is a limitation though, the member function(i.e. a function that is associated with a class, a method) you want to register must accept only one argument, a void* pointer and must return void. Also you have to explicitly declare the time when the callback will happen i.e. when your method will be called. The time must be an uint32_t variable which will contain the microseconds(μs) the timer will count down to expire and call your method. For example to call a method sayHello from object Hello in 5seconds:

uint32_t timeval=5000000;
//here the pointer points to our data, Hello is the class sayHello method belongs to and myHello is our object of class Hello
timer.set_timer(timeval, &myHello, pointer);

Let's see a more complecated example, shall we?

Suppose that you have declared this testClass class.

class testClass
{
	public:
		void charHelloWorld(void *pointer);
		void stringHelloWorld(void *pointer);
	private:
		AndrDebug testDebug;
};

void testClass::charHelloWorld(void *pointer)
{

	testDebug.debug("%s", pointer);
}

void testClass::stringHelloWorld(void *pointer)
{
	string p;
	p=*static_cast(pointer);

	testDebug.debug("%s", p.c_str());
}

As you can see the class contains two methods(member functions) that accept a void* argument and return void. Both methods print the data of the pointer that points using the debug method from AndrDebug class. Obviously in both methods it is predefined in what type the pointer will point.

On another part of the program:

...
//declaring a new AndroidTimerMode object
AndroidTimerModel timer;
//declaring a new testClass object
testClass test;
//declaring char pointer to use the as the data to testClass functions
char *pointer = (char *) malloc(sizeof(50));
char *pointer2 = (char *) malloc(sizeof(50));

uint32_t timeval=5500000; //5.5 seconds
strncpy(pointer,"1st Call", sizeof("1st Call"));
timer.set_timer(timeval, &test, pointer); //line 11
...
timeval=8000000; //8 seconds
strncpy(pointer2,"2nd Call", sizeof("2nd Call"));
timer.set_timer(timeval, &test, pointer2);
...
string *s1 = new string("3nd Call");
timeval=10000; //10msec = 0.01 seconds !!
timer.set_timer(timeval, &test, s1); //line 19
...
string *s2 = new string("4nd Call");
timeval=12000000; //12seconds
timer.set_timer(timeval, &test, s2);
...

At the top level the class objects are created. When a new AndroidTimerModel object is created, the event array and the signalHandler are initialized. In every case we initalize the timeval value, the pointer that holds the data and call the set_timer member function of class AndroidTimerModel to register the callback. As you can see the third register will be the first that will be called since it will be executed in 10msec by the time is registered. The second method that will be retrieved is the first register call and will be executed in 5 - 0.01 - (execution time between lines 11 and 19) seconds.

The prototype of set_timer looks like:

//template method that sets a new event in the timer concept
template
int set_timer( millis_t millis, T *obj_pnt, void *userdata );

It's a rather complicated protype but this happens due to the lack of true object-oriented member function pointers in C++. All you have to remember is that the first two arguments are the class of the member function you hant to register and a pointer to the member function. The next three arguments are the time you want your method to be retrieved, a pointer to the actual object of your class and the data your method will receive.

If you are developing a C++ application for android and you need this features, all you have to do is to include these files(.cpp file is needed for initializing the static struct array) cbox/android_wiselib/androidConcepts/timerConcept/timer.h cbox/android_wiselib/androidConcepts/timerConcept/timer.cpp