Re: Address identity of functions
Hi, I believe I a have an example where relaxing the rule will result
in
unexpected result (at least from the point of view of the user).
I'm working on a template library who's main purpose is to simplify
message-
based communication between threads. It alleviates the task of:
defining the
message, allocating, initializing, sending, dispatching and
deallocation of
the message. Thus, message as a concept is moved from user code and
into the
library.
Basically, the library just sends polymorphic function objects (like
the
internals of std::function) instead of POD messages. However, in
contrast to
std::function, the library allows extraction of the content of the
function
object (for the purpose of this discussion, a function address and,
optionally, function arguments) _without_ 'executing' the function
object.
The purpose of this is to support the equivalent of waiting for a
specific
message id when using POD messages.
The code below is _not_ an example of using the library. It is a mix
of
adjusted library internals and user code - intended to keep the
example as
short as possible and yet complete, without the full library.
#include <iostream>
#include <memory>
#include <queue>
using namespace std;
class TypedGetIf
{
public:
virtual ~TypedGetIf() {}
};
template<typename T>
class TypedGet : public TypedGetIf
{
T* m_value;
public:
TypedGet() : m_value(0) {}
T* get() const { return m_value; }
T* set(T& t) { m_value = &t; return m_value; }
};
template<typename T>
T* set(TypedGetIf& g, T& t)
{
TypedGet<T>* p = dynamic_cast<TypedGet<T>*>(&g);
return p ? p->set(t) : 0;
}
class MessageIf
{
public:
virtual ~MessageIf() {}
virtual void dispatch() = 0;
virtual void get(TypedGetIf& g) = 0;
};
template<typename R>
class Message0 : public MessageIf
{
R (*m_fn)();
public:
Message0(R (*fn)()) : m_fn(fn) {}
virtual void dispatch()
{
cout << "dispatch() calls " << (void*)m_fn << endl;
(*m_fn)();
}
virtual void get(TypedGetIf& g)
{
set(g, m_fn);
}
};
int foo() { return 0; }
int bar() { return 0; }
int baz() { static int i = 0; return ++i; }
int qux() { static int i = 0; return ++i; }
int beforeFoo()
{
cout << "beforeFoo() called" << endl;
return 0;
}
int main(int argc, char* argv[])
{
queue<MessageIf*> queue; // Thread B's input queue
// Thread A sends four messages to thread B's queue
queue.push(new Message0<int>(&foo));
queue.push(new Message0<int>(&bar));
queue.push(new Message0<int>(&baz));
queue.push(new Message0<int>(&qux));
// Thread B's message loop
while (!queue.empty()) {
auto_ptr<MessageIf> msg(queue.front());
queue.pop();
TypedGet<int (*)()> tg;
msg->get(tg);
// We need to treat foo and baz special
if (*tg.get() == &foo) {
beforeFoo(); // Do something before calling foo()
}
else if (*tg.get() == &baz) {
continue; // Ignore all baz 'events'
}
msg->dispatch();
}
return 0;
}
Kind Regards
Kian Karas
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]