Re: Assigning a member function to signal callback function pointer
On Dec 24, 7:04 pm, Ramesh <rrame...@gmail.com> wrote:
Hello,
I am writing an application in linux using timer_create API to create
timers in my application, I have registered a call back routine which
would be called when the timer timesout. I get the following error:
-------
test.cpp: In member function 'unsigned long
testMgr::addConfigChangeTimer(unsigned long)':
test.cpp:125: error: argument of type 'void (testMgr::)(sigval_t)'
does not match 'void (*)(sigval_t)'
------
The compiler expects a function returning void and taking a sigval_t
as argument, in my case the only difference is that the linkage is C++
style and its a member function.
Is there a way I can assign a member function to the notify_function
pointer?
Thanks
/R
Here is the code snippet:
---
// Actual point of assignment of the callback function to the signal
handler
unsigned long testMgr::addConfigChangeTimer(unsigned long interval) {
timer_t id = 0;
int count = 0;
struct sigevent sig;
struct itimerspec timerspec;
memset(&timerspec, 0, sizeof(struct itimerspec));
memset(&sig, 0, sizeof(struct sigevent));
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = ConfigChangeHandler;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sig.sigev_value.sival_ptr = (void*)&count
Do you actually mean to pass the address of the local variable count
to an asynchronous callback function here?
Anyways, like Sam said you can't pass a pointer to a member function
as a callback and expect it to be called on the appropriate instance
of the object. Pointer-to-members do exist, and you can use them but
only if you also supply an instance of a class. The compiler error you
received is because you attempted to pass a pointer to a non-static
member function but it was expecting a pointer to a static/non-member
function (the two have different types).
Instead, pass your 'this' pointer through sig.sigev_value.sival_ptr,
and make your callback a static function. Then your callback can
either do what it needs to do or pass control off to a non-static
member function appropriately, e.g.:
class testMgr {
public:
unsigned long addConfigChangeTimer (unsigned long);
private:
void ConfigChangeHandler ();
static void StaticConfigChangeHandler (sigval_t value);
};
unsigned long testMgr::addConfigChangeTimer (unsigned long) {
...
sig.sigev_notify_function = StaticConfigChangeHandler;
sig.sigev_value.sival_ptr = (void *)this;
...
}
void testMgr::StaticConfigChangeHandler (sigval_t value) {
// pass control to member function.
assert(value.sival_ptr);
((testMgr *)value.sival_ptr)->ConfigChangeHandler();
}
void testMgr::ConfigChangeHandler () {
// do stuff.
...
}
If you want to pass additional context data to ConfigChangeHandler
then you'll have to pack stuff in to some kind of structure, e.g.:
struct ConfigChangeHandlerParams {
ConfigChangeHandler *inst;
int *pcount;
};
void testMgr::StaticConfigChangeHandler (sigval_t value) {
// for example, passing pcount:
assert(value.sival_ptr);
ConfigChangeHandlerParams *p = (ConfigChangeHandlerParams *)
value.sival_ptr;
p->inst->ConfigChangeHandler(p->pcount);
}
Managing ConfigChangeHandlerParams structs in an exception-safe way is
left as an exercise.
HTH,
Jason
-------
// Actual function
void testMgr::ConfigChangeHandler(sigval_t value) {
ACE_Guard<ACE_Thread_Mutex> guard(tMutex);
if (ConfigChange == TRUE) {
Notifythreads();
ConfigChange = FALSE;
}
trace("Config change timeout process completed");
}
----
// Class definition
class testMgr {
private:
timestamp ChangeTime;
BOOL Confi=
gChange;
ACE_Thread_Mutex tMutex;
public:
testMgr();
~testMgr();
UINT32 addConfigChange=
Timer(UINT32);
void entConfigChan=
geHandler(sigval_t );
};