
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I wonder if it might be better/possible to have a shared_ptr<T> that didn't assume its corresponding "raw" pointer type was T* but rather T. For example, what is now a shared_ptr<int> would be specified as a shared_ptr<int*>. The motivation would be to allow support for other classes as the "raw" pointer type. For example, I might want to have a shared_ptr<monitor<T*> > where the monitor<T*> has an operator->() which does automatic locking/unlocking of a mutex before/after forwarding the operator->() to the plain T pointer. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpWA5YACgkQ5vihyNWuA4UQOwCeI7sjr4/pByXIqRtactVfi8fk MUgAoLmstL+7V5NW+yYNXyDPlVog7VAI =JE48 -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 09 July 2009, Andrey Semashev wrote:
Yes, that is in fact what I did: http://www.comedi.org/projects/libpoet/boostbook/doc/boostbook/html/poet/mon... However, it seems like more work to have to provide a full shared_ptr interface, than to implement a plain pointer interface. And perhaps more significantly, a monitor_ptr is a completely different type than a shared_ptr. So, for example, a monitor_ptr can't be passed to a function that expects a shared_ptr as an argument. Also, if there are other applications for pointer wrapper classes, they could be mixed an matched in any combination by the end user in this scheme, like shared_ptr<monitor<pointer_wrapper<T*> > > Maybe, for example, a pointer wrapper class might enforce that the wrapped pointer may never be NULL, to implement a shared_ptr that acts something like a "smart reference". -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpWLu4ACgkQ5vihyNWuA4WFAgCgj2hnsj5uZs1R78+YI2UVVLz0 0tYAoKLA67xb4pgNJXSkr9XbO+Hi7pcH =2OvX -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
You don't have to reimplement shared_ptr interface, unless you really need it. And that interface isn't that sophisticated, anyway.
Types shared_ptr<monitor<T*> >, shared_ptr<T*> and shared_ptr<T> are not compatible either, so you don't win here anything.
IMHO, one of the remarkable features of shared_ptr is its simplicity. All additional features that you describe, while being useful, are out of scope of this simple tool. I agree that some more elaborate policy-driven smart pointer would be useful to implement those things. It just isn't related to shared_ptr in any way. IIRC, Andrei Alexandrescu tried to develop such a pointer, I'm not sure how successful he was.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 09 July 2009, Andrey Semashev wrote:
That's mostly true, however suppose you have a function like template<typename T> myfunc(shared_ptr<T> sp); You might say it could be replaced with something more generic like template<typename SharedPtr> myfunc(SharedPtr sp); but perhaps myfunc creates a weak_ptr<T> from the incoming parameter. The more generic version won't work because shared_ptr doesn't include a typedef for its corresponding weak_ptr type. Also, the more generic version of myfunc might cause conflicts if myfunc has other overloads. You'd be forced to add specialized code for each additional shared_ptr-like class you introduce, or something like type traits for them.
IMHO, one of the remarkable features of shared_ptr is its simplicity.
I agree.
Perhaps I should have distanced my idea from shared_ptr more in presenting it, as I know making interface changes to shared_ptr is almost unthinkable at this point. But it's obviously a related idea, in that generalized_shared<T*> would be equivalent to shared_ptr<T>. And also I imagine generalized_shared could be implemented by copying the entire shared_ptr codebase and then making only minor changes. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpWT/0ACgkQ5vihyNWuA4U1RACggaAZopOtBZj2Nv2X58JdCL/D g1kAoIvAa/D9e1c6N5Z4jfbWgVk3FuZZ =5jFA -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
And also I imagine generalized_shared could be implemented by copying the entire shared_ptr codebase and then making only minor changes.
shared_count can already take an arbitrary P/D pair, so you only need to copy shared_ptr itself, not the rest of the codebase.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 10 July 2009, Peter Dimov wrote:
Ah, ok. Based on your encouragement (at least in the relative sense, since everyone else's response has been negative :), I've implemented a first pass at generic_shared. For those just tuning in generic_shared is like a shared_ptr but can accept a more generic type as the "pointer". It can accept either a plain old pointer as its template type, or a class which: 1) has operator->() and operator*() 2) either has value_type/reference/pointer member typedefs, or a specialization of boost::smart_pointer_traits 3) has a is_null_pointer() free function findable by ADL 4) supports (in)equality comparison generic_shared can also be used by another smart pointer class with similar requirements, since it fulfills them all itself. So you could have monitor<generic_shared<T*> > , to bring back the monitor example. The code is in the file generic_shared.hpp (a fork of shared_ptr.hpp from trunk) which is located in the sandbox directory: https://svn.boost.org/trac/boost/browser/sandbox/fmhess/boost/smart_ptr The file can be copied into the main boost tree (I've been testing it with trunk). There is also a shared_ptr.hpp in the same directory, which implements shared_ptr on top of generic_shared. I used that mainly so I could do some testing of generic_shared using the shared_ptr tests unmodified. The tests pass, except for those which use enabled_shared_from_this or weak_ptr. Beyond that, I've played around a little with a few basic tests that use a user-defined pointer type, and also use a list iterator as the pointer type (with a deleter that uses the iterator to erase the element from its list). So, the current status is: no generic_weak (analogous to weak_ptr) yet, and no shared_from_this support. Also, there is an unresolved issue with respect to casting for non-plain old pointer types. generic_shared tries to apply boost::static/const/dynamic_pointer_cast to its pointer type, but ADL doesn't work for boost::static/const/dynamic_pointer_cast, and specialization won't work either. It seems I'll need to add a ADL hook for casts as suggested at the end of this thread: http://lists.boost.org/Archives/boost/2006/06/106406.php so user-defined pointer types can be support casting. So, before I spend any more time on it, is this something worth pursuing further as far as boost goes? Does it stand any chance of making it into the smart_ptr library? Is there a silent majority out there who thinks this is a worthwhile idea, or is it just me? I might even settle for a vocal minority :) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpc0TMACgkQ5vihyNWuA4VC6ACfW9UfTkCHTbmPc8a+VH2oFU/c XDEAn2B8wckssSMUL9yK1XUqZPfCyl1r =u9n9 -----END PGP SIGNATURE-----

On Tue, Jul 14, 2009 at 1:40 PM, Frank Mori Hess<frank.hess@nist.gov> wrote:
I would use the heck out of something like this. However I was disappointed to see in the comments that the null_value member was replaced by a search for a free function lookup. If traits are going to be supported at all, I think they should be supported first-class, and allow one to just parameterize the class with a traits class to begin with. Every example in boost that I can think of off the top of my head where something relies on either a free-function overload or a template specialization of something (which admittedly isn't too many, but at least 2 or 3 anyway) I have always encountered limitations in in my own usage and had to roll my own similar class for some specialized usage. Maybe this has been discussed in similar contexts before and there's some general consensus, but why not just (note this code assumes that all specializations of smart_pointer_traits in the version in sandbox remain unchanged): template<class T> struct default_smart_pointer_traits : public smart_pointer_traits<T> { static bool is_null(pointer p) { return (p == 0) ? true : false; } }; template<class T, class Traits=default_smart_pointer_traits<T> > class generic_shared { }; As long as the interface required of a traits class is very small, then the class still remains equally simple to use. I don't have an immediate use case in mind for wanting two different instances of generic_shared<> to check for NULL differently, but I know I've been burned more than once in the past by classes requiring free function overloads, so I just want to address it in advance. Zach

Zachary Turner wrote:
It's interesting you should say that, because I have had exactly the reverse experience. I find free function overloads much superior to traits classes for simple things like this. For example, I think boost::hash is better than std::hash because it uses a free function and ADL to find the hashes of my classes. The main advantage is the possibility of using enable_if which allows one function overload to apply to many classes. Can you be more explicit about the problems you have had? John Bytheway

On Tue, Jul 14, 2009 at 4:42 PM, John Bytheway<jbytheway+boost@gmail.com> wrote:
The most recent experience I had is in regards to providing custom validators for types in boost::program_options. I actually made a thread about this a day or two ago on this list, which you can probably find in the most recent 20 or 30 threads. But the gist of it is that I wanted to allow the user to specify an integer on the command line, and I wanted to enforce that the integer was within a certain range. Since boost::program_options has built-in support for validation I figured I'd use it. But, validation is enabled by a free-function overload on the type of the parameter. so you can provide validation for ints, validations for Foo's, etc, but you can't provide validation algorithm A for this specific command line option, and validation algorithm B for that specific command line option. It's not hard to just wait until the entire thing has been parsed and then check that each one it's in a certain range, but still, builtin support for validation has been implemented, so it would be nice if it was generic enough to handle a wide variety of validation scenarios. Another experience I had which I also made a thread about a week or so ago was with regards to intrusive_ptr. Turns out that what I wanted wasn't _technically_ covered by the design goals of intrusive_ptr, but nonetheless it would have been possible if intrusive_ptr used ref_counting_traits with a compile-time interface mandating an add_ref and release function, rather than free function overloads. I basically wanted a way to provide different strategies for managing the same reference count on different instances of the same type. There was at least one other scenario where I was burned by this, but I can't remember it off the top of my head as it was quite a while ago. Regarding enable_if, I didn't actually think of that. But is there a reason that if the generic class in question uses a default traits class as I suggested, that a user cannot simply provide a template specialization of that same class that uses the class template version of enable_if to achieve a similar effect?

On Tue, Jul 14, 2009 at 6:04 PM, Zachary Turner<divisortheory@gmail.com> wrote:
My standard answer has now become: 1. use a traits/policy class 2. have the default traits/policy call a free functinon eg: // default free function // or yours will found by ADL if you supply your own // template<class T> bool is_null_pointer(T p) { return (p == 0); }; // default policy class, calls whatever it finds by ADL // feel free to supply your own policy class instead // template<class T> struct default_smart_pointer_traits : public smart_pointer_traits<T> { static bool is_null(pointer p) { return is_null_pointer(p); } }; Tony

Gottlob Frege wrote:
That's a very nice approach. You seem to lump traits and policy classes together, but they are clearly not equivalent. I think a policy class is superior to a traits class, so your numbered bullets should not contain "traits/". What about function templates? The above seems to apply to class templates only. Overloading permits one function template to rely on a default functor type while another can take a functor as an argument. (The former can call the latter, of course.) The functor argument can be defaulted, provided the default functor is stateless. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Wednesday, July 15, 2009, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Yes I really mean policy. But the original example had a class called 'traits' being passed as a policy and I wanted to make sure it was understood which class I was talking about. I should have clarified more.
What about function templates? The above seems to apply to class templates only. Overloading permits one function template to rely on a default functor type while another can take a functor as an argument. (The former can call the latter, of course.) The functor argument can be defaulted, provided the default functor is stateless.
I think we could make something work. Do you want to start with an example?
_____ Rob Stewart
Tony

Zachary Turner wrote:
I don't think there is a single best way to handle customization. It depends upon whether a class template or a function template is being customized, at the least. Neither traits classes nor customization functions are as flexible as policy classes for class templates. A class template can be parameterized with a policy, likely defaulted to something reasonable, which defines the desired behavior once for all uses of that type. Being a policy class, however, the default can be overridden. The same is not true for traits. For function templates, however, a policy class isn't as convenient as the other options because it must be provided for each invocation, even when the default is wanted. A function template could accept a defaulted functor argument, of course, though deviating from the default requires passing the functor for each invocation. I suspect the desired parameter validation scheme requires providing a functor when defining a particular parameter. That's not onerous since each parameter is registered just once. The same approach would be a problem with a hash function, however. That scenario probably is better served by a hashing function object that relies on a policy class to control the behavior of its function call operator (a set-it-and-forget-it approach).
I was wondering the same. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Zachary Turner wrote:
OK, I understand a little better now. In each case you want to be able to provide different behaviour for different uses of the same type. I agree with other posters that perhaps this is a confusion between traits and policies. I struggle to imagine the same pseudo-pointer type requiring two different meanings of what null is, but that may be a lack of imagination on my part :).
You can, but only if the author of the class template provides a spare template parameter for this purpose defaulted to void. e.g. template<typename Pointer, typename Enabler = void> class pointer_policy { // ... }; and I've never seen any library do that. Moreover, you *can't* do that if the template is variadic. John Bytheway

On Wed, Jul 15, 2009 at 11:31 AM, John Bytheway<jbytheway+boost@gmail.com> wrote:
Yes, that was my bad. I should have said policy and I said traits. I can't think of an immediate use off the top of my head either, but with my luck it will happen someday. like more or less of a deviation than adding a default policy. I can understand the desire to keep it simple and similar to shared_ptr. But I guess we have to define what is considered similar vs dissimilar. Adding an additional argument with a default type allows them to be used with identical syntax. One could grep their entire codebase, replace all occurences of shared_ptr with generic_shared, recompile and the code would behave correctly. I think that's pretty similar.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 15 July 2009, Zachary Turner wrote:
In that case, if I was going to add just one policy template parameter, why would it be policy support for is_null? Why not any of the policies supported by Loki::SmartPtr? Most of them have to be more useful than is_null, since we haven't even come up with a use case for wanting an is_null policy.
This is somewhat analagous to the is_null() function.
Deleters don't effect the type of the shared_ptr. What action a shared_ptr should take when its reference count reaches zero (the deleter) is a property of the shared_ptr. But whether or not a pointer object of type T is null or not is a property of the pointer object, not a property of whatever generic_shared<T> it may happen to be wrapped inside (except in the sense that the generic_shared<T> exposes the existing properties of T).
but shared_ptr definitely does allow per-instance customization of at least 1 aspect of the object being contained.
As I noted above, deleters are a customization of the reference-counting features of shared_ptr, not a method of reinterpreting the properties of the pointer the shared_ptr contains.
I don't consider is_null_pointer a customization. It's a query that allows generic_shared to discover a property of the pointer it contains. It's not meant to set or create properties. Also, if you wanted to change the behavior of is_null_pointer per instance, you can do so. is_null_pointer is passed a pointer to the object in question and can ask the object whether or not it wants to be considered null. And if the pointer class is some 3rd party type, you could wrap it inside your own pointer wrapper class if you need to add extra per-object state to decide if the object is null or not. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpeNoUACgkQ5vihyNWuA4UPYwCghDSJvayRAUBTjFNWdh1AgS6b /AQAoJ7CysijDtJ1N1pG+B/woPZA1cfc =jFPM -----END PGP SIGNATURE-----

On Wed, Jul 15, 2009 at 4:05 PM, Frank Mori Hess<frank.hess@nist.gov> wrote:
A few thoughts, in reply to this post as well as a few others above: - if you are looking for examples for when you might have different behaviours for the same *type*, maybe Win32 loosely typed 'handles' might help. ie: generic_shared<HWND, ...> generic_shared<HMENU, ...> etc Depending on your compile settings (ie #define STRICT) you may have HWND == HMENU == int (or not). But you might want their behaviours to be different. Same might apply to intrusive_ptr<HMENU>, etc. (For example, depending on how HMENUs are created (Dynamic or from RC file) they may or may not be automatically ref-counted by Windows. etc.) - Maybe a more generic smart_ptr IS what we need (ie towards Loki policy-based SmartPtr). Particularly since I've seen the same discussion about intrusive_ptr. Or maybe not. It is worth considering. One ptr to rule them all? (There would still be the specialized smart_ptr and intrusive_ptr of course, for simplicity and compatibility.) - The REAL question is what are the properties? ie the Concepts? ie I see a post above listing the properties of the internal 'pointer': 1) has operator->() and operator*() 2) either has value_type/reference/pointer member typedefs, or a specialization of boost::smart_pointer_traits 3) has a is_null_pointer() free function findable by ADL 4) supports (in)equality comparison Leaving aside the details of free function vs policy, are these all the requirements of the pointer? What about 5) deletion. (currently covered via the optional deleter function in smart_ptr, but I'm just trying to list everything). Does this also cover the requirements for intrusive_ptr? Any other 'smart' pointer? Obviously for intrusive_ptr we would add the requirements of 6) has internal refcount - ie supports incr_ref/decr_ref (somehow - ie currently via ADL) 7) ? And lastly, what are the Concepts that the smart_ptr itself is implementing? 1) it acts like a pointer (ie 1, 2, .... above) 2) is resetable? 3) convertable to weak pointer? Or is that external to smart_ptr? 4) once set/initted it won't suddenly become null (I think that's the main point, right?) Is it the same for all smart pointers? Regardless of whether anyone writes the POE (Pointer Of Everything - ie Theory Of Everything in Physics), it might be worthwhile to sort out these conditions so that we know what is currently being written (if anything). And then maybe we could even decide which pieces should be traits/policies/ADL/constructor_params/etc/etc/etc At least I'd find it interesting. Tony

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 16 July 2009, Gottlob Frege wrote:
I suggest searching the archives of this mailing list for background first. For example, there were many long threads about this in 2002, for example: http://lists.boost.org/Archives/boost/2001/12/22063.php -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpfH7YACgkQ5vihyNWuA4V3PgCfVP9FB8/JEcwl+cOWEjFdLLW9 iMwAoIRxqrgZRT0K8eMzAxtR7dAfti2Z =DFLH -----END PGP SIGNATURE-----

On Thu, Jul 16, 2009 at 8:40 AM, Frank Mori Hess<frank.hess@nist.gov> wrote:
That is somewhat my point - the topic keeps coming up, so maybe we should finally do it. (Or maybe we need a FAQ saying "don't go there".) In 2002 there seemed to be lots of policy design discussion. It would be interesting to know if we've learned anything over the years. Tony

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 17 July 2009, Gottlob Frege wrote:
That is somewhat my point - the topic keeps coming up, so maybe we should finally do it.
There was the policy_ptr proposal for boost, which I assume is still in the sandbox. I even found it listed on some old web copies of the boost review queue pages, I'm not sure what ultimately happened.
(Or maybe we need a FAQ saying "don't go there".)
I don't want to tell other people they shouldn't work on it, but my personal opinion is that designing the ultimate policy based smart pointer that is everything to everyone is a tar pit (which I'm going to avoid).
In 2002 there seemed to be lots of policy design discussion. It would be interesting to know if we've learned anything over the years.
Well, in 2001 we got Loki::SmartPtr. In the next couple years we had a bunch of design debate in boost over a boostified version. Now we're in 2009, and somehow shared_ptr is still king. What I take from that is that there is a place for exploring other approaches to generalizing smart pointers, such as the nested matryoshka doll approach I'm playing with in generic_shared. And also that I want people who think I should just add a policy template parameter or two, and giving them default values will solve everything, to leave me alone :) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpgcyoACgkQ5vihyNWuA4XI8gCfTxh9xUUz/t9DJM6c43rrqUso LWoAn0yZqFat2msQ188hqWHIQwj/XmsJ =NwTK -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 14 July 2009, Zachary Turner wrote:
I don't intend to add additional template parameters to generic_shared. I like shared_ptr, and plan to stay as close to the shared_ptr design as possible. If you want to go the route of high configurability and multiple template parameters, it would probably be better to start from the design of Loki::SmartPtr than boost::shared_ptr. My only goal is to make an incremental deviation that adds support for more than just plain old pointers as the wrapped pointer type. Incidental to that is defining some concepts that will allow conforming smart pointer classes to use each other as their underlying pointer type. Other than that, I plan to ape the shared_ptr interface as closely as possible. It may be that I just alienate both camps, with the "simplicity" people ignoring it as too complex and the "configurability" people wanting more, but that's the road I'm on. The traits stuff in generic_shared is only intended to communicate the necessary information about a pointer-like class to generic_shared, not to provide a customization point for the wrapped type. Such customization would belong in the template parameter list of the wrapped class (the T in generic_shared<T>) anyways, not the class wrapping it. And if it were really absolutely necessary, the customization could be inserted as a wrapper class in between generic_shared and T, like generic_shared<my_customization_wrapper<T, mypolicy> > -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpd348ACgkQ5vihyNWuA4V67QCgnkqeKdMNV0lag3u5BfMoYnPt iyEAoJoE3fBpGkFy8YrU9aJCPMIpK9VJ =+aij -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 14 July 2009, Frank Mori Hess wrote:
A little status update: I've got generic_weak and enable_generic_shared_from_this done, and now all the smart_ptr library tests pass (with the exception of one test that uses enable_shared_from_this2) using wrappers for shared_ptr/weak_ptr/enable_shared_from_this which are built on top of generic_shared/generic_weak/enable_generic_shared_from_this. Pointer casts for non-plain old pointer types works now also. There's no documentation or tests though (beyond the smart_ptr tests). -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpmK30ACgkQ5vihyNWuA4VTLwCgkLACR5WGHKnXQQQ8zd+FIGEp wN0AnR3eakDRViY+eOuhyFXer/QxbwAL =M/Hu -----END PGP SIGNATURE-----

If I'm not mistaken, the C++0x committee is setting the 'shared_ptr<>' class in stone as we speak. I seriously doubt that can be changed this late in the game, considering the amount of code that is already using this class as-is. See if this type of code works for you: #include <boost/shared_ptr.hpp> using boost::shared_ptr; struct mutex { void lock() {} void unlock() {} }; template< typename T > class monitor; template< typename T > class locker { mutex & mutex_; monitor< T > * monitor_; public: locker( monitor< T > * mt, mutex & mx ) : mutex_( mx ), monitor_( mt ) { mutex_.lock(); } ~locker() { mutex_.unlock(); } monitor< T > * operator->() { return monitor_; } }; template< typename T > class monitor { mutex mutex_; public: shared_ptr< T > obj_ptr; monitor( T * t ) : obj_ptr( shared_ptr< T >( t ) ) { } locker< T > operator->() { return locker< T >( this, mutex_ ); } }; int main( int argc, char * argv[] ) { char * buf = new char[ 3 ]; memset( buf, 0, 3 ); monitor< char > m( buf ); *m->obj_ptr = 'A'; return 0; }

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 09 July 2009, Sid Sacek wrote:
I'm not under any delusions about getting such a change to std::shared_ptr into c++0x. That doesn't preclude something like this being added to boost though, under a different name (I'll call it "generalized_shared" for the moment). Then boost::shared_ptr could be implemented as template<typename T> class shared_ptr: public generalized_shared<T*> {...}; -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpWL90ACgkQ5vihyNWuA4Uk2ACcDr+WxE2Ku00ljjQRnUB+1n/c m4EAnjYLI/S+5KyIgopMyLFrI9xX10vB =cOH8 -----END PGP SIGNATURE-----

This was fun to experiment with. Here's another whack at your puzzle. -Sid Sacek #include <iostream> #include <boost/shared_ptr.hpp> using namespace std; using boost::shared_ptr; template< typename T > class monitor; template< typename T > class locker { shared_ptr< T > shared_obj_; public: locker( shared_ptr< T > &shared_obj ) : shared_obj_( shared_obj ) { shared_obj_->lock(); } ~locker() { shared_obj_->unlock(); } shared_ptr< T > operator->() { return shared_obj_; } }; template< typename T > class monitor { shared_ptr< T > shared_obj_; public: monitor( T * t ) : shared_obj_( shared_ptr< T >( t ) ) { } locker< T > operator->() { return locker< T >( shared_obj_ ); } }; struct mutex { void lock() { cout << "object locked \n"; } void unlock() { cout << "object unlocked \n"; } }; struct Q : mutex { void ModifyObject() { cout << "Object modified \n"; } }; int main( int argc, char * argv[] ) { monitor< Q > m( new Q ); m->ModifyObject(); return 0; }

On Thursday, July 9, 2009, Frank Mori Hess <frank.hess@nist.gov> wrote:
I don't think lock/unlock on each -> call is typically a good idea. x = p->x; y = p->y; That's 2 lock unlock sequences instead of one. Inefficient and what if y changes after you read x? It hides the locking too much, potentially leading to abuse and mistakes. I think alexandrescu has an article about this somewhere. (he also has articles about how to implement locking -> operators but I think he later recanted on the whole idea) Tony

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Gottlob Frege
I agree and disagree. I would at some point want to create a class similar to what's being described, but would not expose it to the rest of the world to use ( and abuse ). A class like that could come in handy, as long as it's used with the knowledge of its strengths and limitations. -Sid Sacek

Sid Sacek wrote:
Tony's on target. You've said you wanted the class to be a shared_ptr, which means it can be used in myriad ways without even knowing the cost. If it were a distinct type, then it couldn't be unknowingly misused. Such a type, were you to create it, should not be a special version of shared_ptr. That also avoids forking relative to C++0x. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 09 July 2009, Gottlob Frege wrote:
My monitor_ptr also supports scoped locks, so multiple calls can be made into the object with one lock/unlock: http://www.comedi.org/projects/libpoet/boostbook/doc/boostbook/html/poet/mon... e.g: monitor_ptr<X> mp; { monitor_unique_lock<monitor_ptr<int> > lock(mp); //locks mutex lock->f();// calls X::f lock->g(); }// lock destruction unlocks mutex However, I was hoping to discuss a generalization of shared_ptr more, I mainly brought up monitors as a motivating example. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpWOiYACgkQ5vihyNWuA4VUTACg4MtjHL+bPqwLH/1qjp7YzKP1 TgIAn3dm4chUiv2iqgpi+L+gIUlsiMRq =kKfs -----END PGP SIGNATURE-----
participants (8)
-
Andrey Semashev
-
Frank Mori Hess
-
Gottlob Frege
-
John Bytheway
-
Peter Dimov
-
Sid Sacek
-
Stewart, Robert
-
Zachary Turner