
Hi Kirit! Kirit Sælensminde wrote:
Edd Dawson wrote:
Hi again, Kirit!
Kirit Sælensminde wrote:
template<typename T> class ref_once_copied { public: ref_once_copied(const T &obj) : obj_(new T(obj)), referenced_(false) { } ~ref_once_copied() { if (referenced_) delete obj_; } operator T &() { referenced_ = true; return *obj_; }
private: T *obj_; bool referenced_; };
That looks like a pretty smart move. The first question I had was about using types so as to eliminate the bool. I.e. arrange for it to return a slightly different type, maybe via a function used to wrap this class.
I did spend a while thinking along those lines, but I failed to come up with anything :(
Now that I'm looking at it again though I'm not sure that I completely understand your implementation. It looks to me like you're always forcing a copy (in the constructor) so what job does referenced_ do?
I'm forcing a copy at the start. Copies of these objects are made a bunch of times (~30, as I say) before they find their resting place inside some functor, F say, created by boost::bind(). But copies of these ref_once_copied objects are cheap, so they don't bother me. Then, when F is called inside the child thread, the function proper is handed these objects as arguments. At that point the conversion operators kick in. Once that's happened, the referenced_ flag is set so that the destructor knows the obj_ members have been used and can be deleted.
I can see that it has value if you move the copy from the constructor into the type cast (the operator T &()), but as it is in the constructor if the reference isn't taken for some reason then it will leak a T.
That's true. But the conversion operator is *always* invoked exactly once, right at the point where the actual function is called. However, I had a nasty thought on the way to work today. By moving away from a reference counted approach, I've lost exception safety. Essentially, I have code that looks very roughly like this inside my async::call(): template< guff > return_type_guff call(const Caller &caller, const Functoid &f, const Argtype0 &a0, ..., const ArgyTypeN &aN) { return make_future( caller, boost::bind(&some_helper, f, wrap(a0), ..., wrap(aN)) ); } Each call to wrap() returns either its argument unmodified (if it's a boost::reference_wrapper or a scalar) else an appropriate ref_once_copied<> made from that argument. But if one of those calls to wrap() throws, I'm going to be leaking left right and center because the ref_once_copied<> destructors won't delete their obj_ members as the conversion operator wont have been called yet. So for now I'm going to go back to reference counting. It's the only way I can think of doing this safely.
It looks like you've changed your mind about the semantics half way through implementing it.
I started out using a boost::shared_ptr<> for the obj_ member, but I realised that approach outlined above would work just as well and also avoid the extra overhead that the reference counting entails.
I agree with this. In a multi-threaded environment those interlocked increments and decrements aren't cheap. A policy based implementation might be nice where we can provide the right threading semantics to the shared_ptr would be cool.
Well I'm leaning towards implementing my own very light-weight reference count for use in ref_once_copied. In my implementation, I shouldn't need any atomic/interlocked stuff at the argument-binding stage as far as I can tell. However, I have to confess I'm still really rather new to multithreading and concurrency which is why I felt the need to create an easy to use mechanism such as this. So I may well be wrong.
So I just wanted to say thanks! I wouldn't have gone down this road if it wasn't for your suggestion. Perhaps you'll find a use for this in your implementation?
I certainly will! :-)
You're the same Edd that has a C++ JPEG library as well aren't you? I've bookmarked it and will have a play with that once I get a chance.
That's me! I'd be interested to hear how you get on with it! I'm toying with the idea of creatng a similar library for pngs, but that won't be for some time, yet. Edd