sean-keys
asked on
Specify call-back member function in c++ templated class constructor
I created the following templated c++ class
Is there a way so that I can specify which member function to call back? Like this:
Thanks,
Sean
template<class ActionClass> class Timer {
public:
Timer(uint32_t initialDelayMS, uint32_t intervalMS, ActionClass* action) : TimerCallback(action), alarmCounter(0) { ....
/**
* The signal handler function with extended signature
*/
static void alarmFunction(int sigNumb, siginfo_t *si, void *uc) {
// get the pointer out of the siginfo structure and assign it to a new pointer variable
Timer *ptrTimer = reinterpret_cast<Timer *>(si->si_value.sival_ptr);
ptrTimer->TimerCallback->TimerCallBack();
}
Is there a way so that I can specify which member function to call back? Like this:
ptrTimer->TimerCallback->SpecifidMemberFunctionFromConstructor
Thanks,
Sean
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ActionClass::MemberName could it be that easy...
ASKER
Timer(uint32_t initialDelayMS, uint32_t intervalMS, ActionClass* action, ActionClass::MemberName) : TimerCallback(action), alarmCounter(0) {
src/inc/Timer.h:26:88: error: 'ActionClass::MemberName' is not a type
Not quite :)
src/inc/Timer.h:26:88: error: 'ActionClass::MemberName' is not a type
Not quite :)
You should be able to exchange 'SpecifidMemberFunctionFro mConstruct or' for that name if I'm not too confused about the setup (hint: the more code, the better)
ASKER
I'll do some digging thx.
FWIW
FWIW
template<class ActionClass> class Timer {
typedef void(ActionClass::*memberFunction)(); //TODO consider passing a function ptr rather than a class
public:
Timer(uint32_t initialDelayMS, uint32_t intervalMS, ActionClass* action, memberFunction MemberName) : TimerCallback(action), alarmCounter(0) {
uint64_t delay = initialDelayMS * NANO_FACTOR;
uint64_t interval = intervalMS * NANO_FACTOR;
this->timerSpecs.it_value.tv_sec = initialDelayMS / MILI_FACTOR;
this->timerSpecs.it_value.tv_nsec = delay - ((initialDelayMS / MILI_FACTOR) * NANO_FACTOR * MILI_FACTOR);
// and then all 3 seconds a timer alarm
this->timerSpecs.it_interval.tv_sec = intervalMS / MILI_FACTOR;
this->timerSpecs.it_interval.tv_nsec = interval - ((intervalMS / MILI_FACTOR) * NANO_FACTOR * MILI_FACTOR);
// Clear the sa_mask
sigemptyset(&this->SignalAction.sa_mask);
// set the SA_SIGINFO flag to use the extended signal-handler function
this->SignalAction.sa_flags = SA_SIGINFO;
// Assign sigaction method
this->SignalAction.sa_sigaction = Timer::alarmFunction;
// Define sigEvent
// This information will be forwarded to the signal-handler function
memset(&this->signalEvent, 0, sizeof(this->signalEvent));
// With the SIGEV_SIGNAL flag we say that there is sigev_value
this->signalEvent.sigev_notify = SIGEV_SIGNAL;
// Now it's possible to give a pointer to the object
this->signalEvent.sigev_value.sival_ptr = (void*) this;
// Declare this signal as Alarm Signal
this->signalEvent.sigev_signo = SIGALRM;
// Install the Timer
if (timer_create(CLOCK_REALTIME, &this->signalEvent, &this->timerID) != 0) {
perror("Could not create the timer");
}
// Finally install tic as signal handler
if (sigaction(SIGALRM, &this->SignalAction, NULL)) {
perror("Could not install new signal handler");
}
//specifiedCallBack = ActionClass::MemberName;
}
virtual ~Timer(){};
void start() {
if (timer_settime(this->timerID, 0, &this->timerSpecs, NULL) == -1) {
perror("Could not start timer:");
}
}
/**
* The signal handler function with extended signature
*/
static void alarmFunction(int sigNumb, siginfo_t *si, void *uc) {
// get the pointer out of the siginfo structure and assign it to a new pointer variable
Timer *ptrTimer = reinterpret_cast<Timer *>(si->si_value.sival_ptr);
ptrTimer->TimerCallback->TimerCallBack();
}
// Stored timer ID for alarm
timer_t timerID;
// Signal blocking set
sigset_t SigBlockSet;
// The according signal event containing the this-pointer
struct sigevent signalEvent;
// Defines the action for the signal -> thus signalAction <img src="http://quirk.ch/wordpress/wp-includes/images/smilies/icon_wink.gif" alt=";-)" class="wp-smiley">
struct sigaction SignalAction;
// The itimerspec structure for the timer
struct itimerspec timerSpecs;
private:
ActionClass* TimerCallback;
void (Timer<ActionClass>::*specifiedCallBack) ();
int alarmCounter;
void DefaultAlarmFunction() {
this->alarmCounter++;
std::cout << "Timer expired but you did not assign an action!! Signal occurred. Count=" << this->alarmCounter
<< std::endl;
}
};
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi Sara
I have a core program with about 10 functions that need to be executed at specified intervals. These are all member functions of instantiated classes, that need to be run. I guess maybe what I could do is remove all the template stuff and create a static member function for each class that calls the timed tasks via an instance pointer etc. At least that would simplify the time class itself.
Thoughts?
Thanks,
Sean
in my opinion your current issues are not because of the complexity of the Problem but of the strangeness of your design.Indeed! I'm a C guy who is just getting back into OOP. Essentially want I want to do is create a timer instance with parameters that determine interval and what call-back to execute. The issue is that the call-back needs to access member data, so I don't really see an easy way to use a static function.
I have a core program with about 10 functions that need to be executed at specified intervals. These are all member functions of instantiated classes, that need to be run. I guess maybe what I could do is remove all the template stuff and create a static member function for each class that calls the timed tasks via an instance pointer etc. At least that would simplify the time class itself.
Thoughts?
Thanks,
Sean
ASKER
Maybe inheritance is the answer...
Maybe inheritance is the answer...yes, probably. you already have a timer class. if you allow to derive from it you could make all the common parameters members of the timer baseclass; special parameters may be members of the derived class. instead of passing a callback function pointer, the timer baseclass may have a virtual function which you could overload in the derived class. additionally, you would use a timer manager class which is a singleton. timer manager has functions addTimer, killTimer and would run a thread to watch over the active timers. if a timer was due, the manager would invoke the callback by a virtual call.
Sara
ASKER
It's really a design problem on my part. Thanks guys, I have enough info to roll a *decent solution.
ASKER
Open in new window
into a ctor parameter... Sorry been away from c++ for years now.