On Thursday, May 03, 2012 4:56 AM, Sven Bauhan wrote:
No, you don't have to make a signleton. The function XtAppAddTimeOut accepts "XtPointer client_data" argument, where you can pass "this". Then you get it back in the callback function, and type-cast it to its original type.
Ok this is another solution. But I don't like such pointer casts. I have done it the following way:
class AnimationController { private: static boost::optional<AnimationController&> cInstance; public: static AnimationController& instance() { return cInstance.get(); } AnimationController() { cInstance = *this; } static void timerCB() { instance().animate(); } private: void animate(); };
Just as praise for boost::optional :-) Sven
The implementation that comes to my mind involves the following helper class or something similar (warning: untested): //A generic wrapper for XtAppAddTimeOut class AppTimeout { public: typedef boost::function <void()> CallbackType; //Constructor registers the app_context and callback, but doesn't start the timer. AppTimeout (XtAppContext app_context, CallbackType callback): app_context (app_context), callback (callback), interval_id (0) {} ~AppTimeout() { Cancel(); //Because the timer would cause undefined behavior if it triggers after the destructor } void Schedule (unsigned long interval) { assert (!interval_id); //This class only supports one timeout per instance interval_id = XtAppAddTimeOut (app_context, interval, &interval_callback, this); } void Cancel() { if (interval_id) //I won't consider redundant calls to Cancel an error; just no effect { XtRemoveTimeOut (interval_id); interval_id = 0; } } bool Is_pending() const {return interval_id != 0;} private: XtAppContext app_context; CallbackType callback; XtIntervalId interval_id; static void Internal_callback (XtPointer self, XtIntervalId*) { reinterpret_cast <AppTimeout*> (self)->callback(); //According to http://www.xfree86.org/current/XtAppAddTimeOut.3.html //a triggered timeout is automatically removed, so clear its id. reinterpret_cast <AppTimeout*> (self)->interval_id = 0; } };