Changes for Timers and Chores

FOX 1.2 introduces some changes to the APIs for setting, handling and removing timers and chores. One benefit of these changes is that they reduce the amount of bookkeeping that an application developer must do in order to ensure that timers and chores are removed. Another benefit is that user-defined message data can now be sent along with the SEL_TIMEOUT and SEL_CHORE messages.

Whenever a timer event "fires", a message is sent to its target (some FOX object). For this reason, FOX application developers must take care that objects which are targets for these messages are not destroyed before those messages are sent. Put another way, you need to be sure to remove the timer, using the removeTimeout() function, before the target object is destroyed. In FOX 1.0, the removeTimeout() function expected a pointer to an FXTimer object:

FXTimer *removeTimeout(FXTimer *timer);

This presented a bit of a bookkeeping problem for application developers. Since you need a pointer to the FXTimer in order to remove it, that means that you must store it somewhere (usually as member data in one of your classes) when it's added using addTimeout(). In FOX 1.2, this approach still works, but a new overloaded version of removeTimeout() allows you to remove timers by passing in the original target and message identifier used to register the timer:

// Register the timeout
void MyClass::startTimer()
{
    getApp()->addTimeout(this, MyClass::ID_TIMER, 1000);
}

// Destructor
void MyClass::~MyClass()
{
    getApp()->removeTimeout(this, MyClass::ID_TIMER);
}

Note that the addTimeout() function still returns a pointer to an FXTimer, but it's no longer necessary to hang on to that pointer. If you want to query the application to determine whether a timer is registered (but has not yet fired) you can use the new hasTimeout() member function:

FXbool hasTimeout(FXObject *tgt, FXSelector sel) const;

Another shortcoming for timers in FOX 1.0 was that the message data sent along with a SEL_TIMEOUT message was a pointer to the application's FXEvent record. In practice, this is not especially useful and you'd rather have some application-specific data there instead. For this reason, addTimeout() now takes an optional fourth argument which just a void pointer to some user data:

FXTimer *addTimeout(FXObject *tgt, FXSelector sel, FXint ms=1000, void *ptr=NULL);

The value of ptr will be sent along with this timer's SEL_TIMEOUT message as the message data. For many applications, this provides a convenient way to pass along some context for the timer event. As you might expect, similiar changes have been made for the addChore() and removeChore() member functions. Chores can now have optional user data:

FXChore *addChore(FXObject *tgt, FXSelector sel, void *ptr=NULL);

and chores can be removed by simply specifying the target object and message identifier for the chore:

FXChore *removeChore(FXObject *tgt, FXSelector sel);

There's also a new hasChore() member function, similar in purpose to the new hasTimeout() member function.