All of that description can be satisfied with a simple handle or proxy object. You have a handle/proxy to the resource. It serves as a long-term reference that can even be persisted.
Yes, exactly. What I'm talking about is an exercise in imagining a non-intrusive, non-centrally-managed system for proxy/handle semantics. You could accurately call the co-pointer I've mentioned "proxy_ptr" if you wanted to (I'm going to for the rest of this reply, just for simplicity). The somewhat new bit compared to the proxy systems I've seen is that I'm using an owning pointer (something like shared_ptr) and an external control block to facilitate notification, rather than central management, or by intruding on the proxied object or its interface. I think that's useful enough on its own, but I also think there's some room to be more efficient than, say, just using shared_ptr. At this point, I think my weekend project will be to write it up and benchmark it to get a more concrete understanding of its realities.
Maybe I don't understand your issue correctly, but isn't that exactly what one would want?
Absolutely, sometimes, probably even most times. What you go on to describe are indeed valid concerns and useful and good semantics if that is your need. In fact, its exactly the semantics of my own current resource manager that I've been quite happy with. But I think its not always the need. There already are a number of people in the "immediate-single-use proxy camp" I'm not inventing that -- just looking for a different solution than is typical and one which ends up looking a lot like shared_ptr/weak_ptr.
I concede that the semantics of my proxy_ptr don't prevent the object from being ripped out from underneath you by a poorly-timed object de-allocation if you hold onto the reference at all, but neither do non-locking proxy systems of any description, or raw pointers in a multi-threaded context for that matter. And one might reasonably object that if you somehow know that a resource is valid anyway, then a raw-pointer is sufficient -- and it is. But sometimes you might not know, or what you did know when you passed the pointer might have changed before you come to use it -- a proxy_ptr as I describe would be useful for independently propagating a checked, immediate-single-use pointer across an epoch where its resource might or might not have been deleted.
In addendum about shared_ptr inc/dec costs: You shouldn't be doing a lot of those anyway.
Agreed. I've already conceded that using a combination of shared_ptr/weak_ptr/raw pointers smartly goes a long, long way towards achieving efficiency. But it also necessarily gives you semantics you might not want, and exposes you to things you might not want to be exposed to -- e.g. leaking a shared_ptr or creating cycles between shared_ptrs that prevents the object from being deleted. Now, those problems are indicative of some other bug, and ideally would be addressed as such, but those tend to be difficult bugs to track down and I've seen more than a few go out into the wild since leaking a little memory usually isn't a catastrophic issue. Certainly other potential bugs come part and parcel with proxy_ptr, but they'd be of the immediately-crashing type rather than the silently-consume-memory type, and I'd rather have the former since it comes with a clue about what needs fixing. That said, I don't know quite what the efficiency wins might be in exact quantities; I think they're there, but proxy_ptr probably isn't very attractive without some gains;
Anyhow, like I said, I think I'm going to write this up this weekend and see what I find in terms of implementation, performance, and properties. When I manage to get to it I'll report back what I find. I'll start a new discussion thread and link to it from here. I suspect it'll be illuminating even if it ends up being a wild goose chase.