| Topic: |
DEVELOP > c-Plus-Plus |
| User: |
"" |
| Date: |
31 Jul 2005 08:26:08 PM |
| Object: |
design woes ... confused on an implementation approach |
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
.
|
|
| User: "Maxim Yegorushkin" |
|
| Title: Re: design woes ... confused on an implementation approach |
01 Aug 2005 03:55:35 AM |
|
|
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.
.
|
|
|
| User: "" |
|
| Title: Re: design woes ... confused on an implementation approach |
01 Aug 2005 09:29:50 AM |
|
|
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.
.
|
|
|
| User: "Maxim Yegorushkin" |
|
| Title: Re: design woes ... confused on an implementation approach |
01 Aug 2005 09:50:58 AM |
|
|
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.
.
|
|
|
| User: "" |
|
| Title: Re: design woes ... confused on an implementation approach |
01 Aug 2005 06:05:19 PM |
|
|
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?
.
|
|
|
| User: "Maxim Yegorushkin" |
|
| Title: Re: design woes ... confused on an implementation approach |
02 Aug 2005 01:30:41 AM |
|
|
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);
// ...
}
.
|
|
|
|
|
|
|
|

|
Related Articles |
|
|