Gottlob Frege wrote:
void intrusive_ptr_add_ref(ObjectStruct * p) { p->refer () ; } void intrusive_ptr_release(ObjectStruct * p) { p->unrefer () ; }
Are you going to make it thread-safe (or is that something you just left out of the example?)?
Well, I left it out of the example since my main focus was on getting it to work _at all_. So, yes, I've seen the multi-threading tricks that shared_ptr & friends do use, and I want to take advantage of that. ... But I'm not there yet, unfortunately. Something that escaped my attention when I first ran (and then posted) the snippet is that I've still got a problem to solve :-(
struct MyTaskStruct : public LongTaskStruct , TaskDoneStruct {
MyTaskStruct() { setCallback(TaskDone(this)) ; }
The problem here, is that setCallback is called from the constructor, at a time when
MyTask myTask(new MyTaskStruct) ;
hasn't finished executing yet. So the "myTask" intrusive pointer doesn'y exist yet. In fact the issue is even more subtle but here it goes: The "TaskDone(this)" is perfectly fine, except that setCallback stores it into a member of MyTaskStruct. In turn, this means that when "myTask" is finally created on the stack, the refCount is alreadly 1. Which it increments to 2. When "myTask" goes out of scope, it rightly decrements the refCount, but because the object itself now embeds a pointer to itself, the refCount never reaches 0. The reason I didn't catch this at first is because, the test case also specified aternate callback in which case the embedded pointer inside myTask is *not* referring to itself, so when nyTask gooes out of scope, the refCount drops to 0 and then the embedded pointer unrefer is called, which in turn destroys the referred to callback. Obviously, this is unacceptable. I'm working on this. The following is a perfectly legal Java idiom which I find all over the place in the source I am porting. Basically it says: For simple use, just use me as is. I implement a default policy regarding so and so. However you are free to specify your own policy when required: interface I { void i() ; } class C implements I { I myI ; void i() { System.out.println("I.i() called, as implemented by C") ; } C() { myI = this ; } void setI(I i) { myI = i ; } void f() { myI.i() ; } } The equivalent C++ code would be something along the lines: struct IStruct { virtual void i() = 0 ; } ; typedef intrusive_ptr<IStruct> I ; struct CStruct : public IStruct { I myI ; CStruct() { myI = I(this) ; } } ; typedef instrusive_ptr<CStruct> C ; But this code would fail because of the above problem, where the embedded myI would refer to the same object as the outer smart pointer. Still digging ... :-( -- JFB