I like your idea of generalizing this solution to enable weak
callbacks in general, but am unable to think of a satisfactory way to
do that. In pricipal it is easy, but the limitations of C++ would
require writting redirection functions for every function in the
interface. I can't think of a clean way to to that automaticly.
Let me brainstorm here for a bit. None of the following ideas
actually work (well some would work but are probably distatefull), but
maybe they will stimulate an idea in someone.
Idea 1:
Add some wrapper layer to C++ that would allow the following:
template<typename T>
class csWeakCallback : T
{
T *imp;
public:
csWeakCallback (T *imp) : imp(imp) { }
<%for $func in functions_of(T)%>
$func () { imp->$func(); }
<%end for%>
};
Idea 1.5:
The same as Idea 1, but use the preprocessor to do that. (Still
probably not possible b/c the preprocessor would need to be able to
figure out what functions a particular interface had.)
Idea 2:
Find some way to take a pointer to a call back interface (e.g.
iEventHandler*) and produce another pointer to that interface with the
same vtable except for the entries for IncRef and DecRef which would
get assigned to no-op functions.
Idea 3:
Establish some way to "poison" the csRefs that are used internally by
what ever the callback is registered with.
Idea 3a: Establish some kind of weak-object system so csRef could tell
that the pointer it is holding is to an object that should always be
held only weakly.
Idea 3b: Make a "poisoned" csRef that would poison any csRef that it
gets assigned to (poisioned = hold the object only weakly). Then when
registering the callback use a csRef instead of a pointer which we
will pre-poison.
On 8/4/06, Jorrit Tyberghein <[EMAIL PROTECTED]> wrote:
> I just considered something. I think this solution is focusing too
> much on event handlers but event handlers are not the only type of
> callback where this problem occurs. I can't give examples right now
> but I'm sure there are many other types of callbacks where similar
> problem occurs right now which is also solved with embedding
> interface. So perhaps we should find a way to generalize this so that
> it can work for a general callback type system?
> Perhaps using a template?
>
> Greetings,
>
> On 8/3/06, Michael D. Adams <[EMAIL PROTECTED]> wrote:
> > On 7/29/06, Jorrit Tyberghein <[EMAIL PROTECTED]> wrote:
> > > > *token = new csWeakEventHandler(listener);
> > >
> > > This is invalid code. You can't use a weak ref like that. Keep in mind
> > > that if the only thing that holds a reference to something is a weak
> > > reference then the object will be removed. You'll have to rework the
> > > code a bit so that after allocation you have a real reference for a
> > > while and then you release that reference as soon as you register to
> > > the event registry.
> > >
> > > I do understand the basic idea of your solution though and it seems
> > > like a possibility.
> >
> > Below is a redraft of the code. I changed two things. But I'm not
> > sure whether I am using csHandlerID correctly for the second change.
> >
> > First, I fixed my use of csRef as Jorrit noted should be done.
> >
> > The second change is to make the csWeakEventListener completely
> > invisible to the client code. Now the csHandlerID that is handed back
> > (by RegisterListener via RegisterWeakListener) is used to lookup the
> > iEventHandler (really a csWeakEventListener) that should be passed on
> > to RemoveListener by RemoveWeakListener. (As a side benefit, this
> > eliminates the need for an output parameter in RemoveWeakListener to
> > hand back the "csRef<csWeakEventListener>*".)
> >
> > As far as I can tell, there are two kinds of csHandlerID, generic and
> > instance. The csHandlerID returned by RegisterListener is an instance
> > csHandlerID. What I'm not 100% sure on is that "instance" in this
> > context means "per object instance". If it doesn't, then this code
> > probably wont work and I should go back to handing back a
> > "csRef<csWeakEventListener>*". So can anyone confirm that
> > understanding of "instance csHandlerID"?
> >
> > Michael D. Adams
> > [EMAIL PROTECTED]
> >
> > // The indirection class. Hidden from client code
> > class csWeakEventHandler :
> > scfImplementation1<csWeakEventHandler, iEventHandler>
> > {
> > private:
> > csWeakRef<iEventHandler> parent;
> > public:
> > csWeakEventHandler (iEventHandler *parent) :
> > scfImplementationType (this), parent(parent) { }
> > bool HandleEvent (iEvent& e) { parent->HandleEvent(e); }
> > /* Similar code to HandleEvent for all the other methods of iEventHandler
> > */
> > };
> >
> > // Helper function used by client code
> > // May be unnecessary. The client code can just call the code on its own.
> > csHandlerID RegisterWeakListener (iEventQueue *q, iEventHandler * listener)
> > {
> > csRef<csWeakEventHandler> handler;
> > handler.AttachNew (new csWeakEventHandler (listener));
> > return q->RegisterListener (handler);
> > }
> >
> > // Helper function used by client code.
> > // May be unnecessary. The client code can just call the code on its own.
> > void RemoveWeakListener (iEventQueue *q, iObjectRegistry *r, csHandlerId id)
> > {
> > q->RemoveListener(csEventHandlerRegistry::Handler(r, id));
> > }
> >
> > // Example client code
> > class csFoo : scfImplementation2<csFoo, iComponent, iEventHandler>
> > {
> > private:
> > csHandlerID id;
> > public:
> > csFoo() : id(CS_HANDLER_INVALID) { /* ... */ }
> > ~csFoo();
> > bool Initialize (iObjectRegistry *object_reg);
> > bool HandleEvent (iEvent& e) { /* ... */ }
> > };
> >
> > bool csFoo::Initialize (iObjectRegistry *object_reg)
> > {
> > /* ... */
> > csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
> > if (q != 0)
> > {
> > id = RegisterWeakListener(q, this);
> > }
> > /* ... */
> > return true;
> > }
> >
> > csFoo::~csFoo ()
> > {
> > /* ... */
> > if (id != CS_HANDLER_INVALID)
> > {
> > RemoveWeakListener(q, object_reg, id);
> > }
> > /* ... */
> > }
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Crystal-main mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/crystal-main
Unsubscribe: mailto:[EMAIL PROTECTED]