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 Crystal-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/crystal-main Unsubscribe: mailto:[EMAIL PROTECTED]