By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,486 Members | 1,696 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,486 IT Pros & Developers. It's quick & easy.

design woes ... confused on an implementation approach

P: n/a
Select parameters in a vendors API file is as follows:

#ifdef __cplusplus
typedef void (*VOIDFUNCPTR)(...); /* ptr to function returning void
*/
#else
typedef void (*VOIDFUNCPTR)(); /* ptr to function returning void
*/
#endif /* __cplusplus */

enum CAUSE { CHAN0_COMPLETE, CHAN0_MISS, CHAN0_HIT, CHAN0_ISM };
bool IntConnect( CAUSE c, VOIDFUNCPTR p, int idx, int jdx);
// end vendors file

The member function IntConnect that takes a cause; a VOIDFUNCPTR; and
a two integer variables.

The basic premise: You'll pass your desired - static/global - member
function + cause, etc .. to the vendors IntConnect member function.

To bypass the 'procedural approach' I have a class transfer that takes
a map and a function pointer.

class transfer {
static std::auto_ptr<cb_base> user_cb;
map<CAUSE, VOIDFUNCPTR> myMap;
static void callback_mem_func1(...) {
// call user function passed in via connect_interrupt
cb_base &cb = *user_cb;
}
static void callback_mem_func2(...) {
// call user function passed in via connect_interrupt
cb_base &cb = *user_cb;
}
/// more

public:
transfer() {
myMap[CHAN0_COMPLETE] = &transfer::callback_mem_func1;
myMap[CHAN0_MISS] = &transfer::callback_mem_func2;
// more
}

template <typename T>
bool connect_interrupt(
CAUSE c,
int param1,
int param2,
T& t,
void (T::*f)(...) ) )
{
map<CAUSE, VOIDFUNCPTR>::iterator it = myMap.begin();
for (; it != myMap.end(); ++it)
{
if ( it->first == c )
{
bool success = IntConnect(
(*it).first,
(*it).second,
param1,
param2
);

if ( success ) {
user_cb.reset(new cb_derived<T>(t, f));
}
break;
}
} // end for
};
With this approach I'll register with IntConnect a static member
function. The static member function will - in turn - call user
desired member function.

At issue: The current approach to user_cb WONT work. I need to have
vector or something similar .. This way within the member functions
callback_mem_func1, etc. I could do:

void callback_mem_func1(...) {
// call user function passed in via connect_interrupt
cb_base &cb = *user_cb[0]; // <<<<NOTE HERE>>>
}
void callback_mem_func2(...) {
// call user function passed in via connect_interrupt
cb_base &cb = *user_cb[1]; // <<<<NOTE HERE>>>
}
or ... I'm open to a re-design worse case.

// cb_base:

# include <iostream>
# include <memory>
# include <string>

using namespace std;
class cb_base
{
public:
virtual void operator()(...) const {};
virtual ~cb_base() = 0;
};

inline cb_base::~cb_base() {}

template <typename T>
class cb_derived : public cb_base
{
public:
typedef void (T::*F)(...);
cb_derived( T& t, F f) : t_(&t), f_(f) {}
void operator()(...) const
{
(t_->*f_)();
}

private:
T* t_;
F f_;
};

template <typename T>
cb_derived<T> make_callback (T& t, void (T::*f)(...) )
{
return cb_derived<T>(t, f);
}

template <class T>
std::auto_ptr<cb_base> new_callback(T& t, void (T::*f)(...))
{
return std::auto_ptr<cb_base>(new cb_derived<T>(t, f));
}
Thanks in advance

Aug 1 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
ma******@pegasus.cc.ucf.edu wrote:
Select parameters in a vendors API file is as follows:

#ifdef __cplusplus
typedef void (*VOIDFUNCPTR)(...); /* ptr to function returning void
*/
#else
typedef void (*VOIDFUNCPTR)(); /* ptr to function returning void
*/
#endif /* __cplusplus */

enum CAUSE { CHAN0_COMPLETE, CHAN0_MISS, CHAN0_HIT, CHAN0_ISM };
bool IntConnect( CAUSE c, VOIDFUNCPTR p, int idx, int jdx);
// end vendors file


Are you sure that VOIDFUNCPTR takes no arguments before the ellipsis?
Because as it's declared now there is no way to get arguments from
inside VOIDFUNCPTR callback.

Aug 1 '05 #2

P: n/a
I'm sure. That is the way VOIDFUNCPTR is declared. It was a surprise
to me when I encountered it. I never understood the need for the
ellipsis.

Aug 1 '05 #3

P: n/a
ma******@pegasus.cc.ucf.edu wrote:
I'm sure. That is the way VOIDFUNCPTR is declared. It was a surprise
to me when I encountered it. I never understood the need for the
ellipsis.


Then it seems to be no way to pass any data to the callback, the
callback has to operate on global data.

Aug 1 '05 #4

P: n/a
Yeah but the more important questions is what's teh workaround for
'user_cb'?. user_cb needs to reflect a list/vector or .......... How
would you achieve this?

Aug 1 '05 #5

P: n/a

ma******@pegasus.cc.ucf.edu wrote:
Yeah but the more important questions is what's teh workaround for
'user_cb'?. user_cb needs to reflect a list/vector or .......... How
would you achieve this?


I'd do something along these lines:

typedef void (*VOIDFUNCPTR)();

enum CAUSE { CHAN0_COMPLETE, CHAN0_MISS, CHAN0_HIT, CHAN0_ISM };
bool IntConnect( CAUSE c, VOIDFUNCPTR p, int idx, int jdx);

template<int N> struct int_ {};

template<int N>
void the_callback(int_<N>); // implement it
// alternatively
// void the_callback(int_<CHAN0_COMPLETE>);
// void the_callback(int_<CHAN0_MISS>);

template<int N>
void callback_thunk()
{
the_callback(int_<N>());
}

void f()
{
IntConnect(CHAN0_COMPLETE, callback_thunk<CHAN0_COMPLETE>, 0, 0);
IntConnect(CHAN0_MISS, callback_thunk<CHAN0_MISS>, 0, 0);
// ...
}

Aug 2 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.