[boost] Re: Proposed smart_handle library
Andrei Alexandrescu [EMAIL PROTECTED] writes: Ah, one more point that was discussed... there was much around operator- and operator* which don't make sense for certain resources. With Loki's SmartPtr, you can disable these two functions. Granted, the error message would be different, such as get_reference not found as opposed to operator* not found. A little judiciously-applied SFINAE can fix that, though. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
I might not have followed the discussion to deeply, but it does look to me like John is entirely right. Traits can fundamentally do one customization per type. That's not going to be enough if you have the same type representing multiple handles, as is the case with many C APIs. For example, sockets and file descriptors might be both integers. Or, a variety of handles can come in the disguise of a void*. In Windows, if you #define STRICT, they use a trick to give different flavors of HANDLEs different C++ types (nothing fancy, it's all casts). Still, they forgot to do that for a couple of handle types (which were that? HBITMAP? HINTERNET? I can only say HGEEITSBEENALONGTIME). So then after a team I was working with built a very nice and sweet smart handle class using traits, we simply couldn't use it because of this particular issue. Indeed, but what about a wrapper for each time of handle, with a conversion operator()? I have used it a couple of times. Something like: struct hbitmap_wrapper { hbitmap_wrapper( HBITMAP h); operator HBITMAP() { ... } ... }; Then in code, instead of HBITMAP, use hbitmap_wrappers. Best, John With a trait, you can only establish one way of dealing with int and one way of dealing with void*. With a policy, you can define at the exact granularity that you want how exactly your handle maps to a type and how it is manipulated - and that policy will be part of the object type. I'm not sure that the inheritance-based approach is superior or not, it sure would be worth some discussion. For more reference on traits, here are two articles that might be of relevance: http://www.moderncppdesign.com/publications/traits.html http://www.moderncppdesign.com/publications/traits_on_steroids.html Andrei ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] - A policy based design to whereas the policy extends the classes interface. - Stronger typing (the types are different based on typename, not on traits). The traits approach seems fundamentally flawed as two separate types could share the same traits. I think that the traits system makes the typing stronger. It guarantees distinct types even in the face of handles that are otherwise indistinguishable. I looked at your design, but I think I can handle what you're trying to do through traits class inheritance. I don't see any use to extending the interface through a policy class. Let me know if I've missed something. I might not have followed the discussion to deeply, but it does look to me like John is entirely right. Traits can fundamentally do one customization per type. That's not going to be enough if you have the same type representing multiple handles, as is the case with many C APIs. For example, sockets and file descriptors might be both integers. Or, a variety of handles can come in the disguise of a void*. In Windows, if you #define STRICT, they use a trick to give different flavors of HANDLEs different C++ types (nothing fancy, it's all casts). Still, they forgot to do that for a couple of handle types (which were that? HBITMAP? HINTERNET? I can only say HGEEITSBEENALONGTIME). So then after a team I was working with built a very nice and sweet smart handle class using traits, we simply couldn't use it because of this particular issue. With a trait, you can only establish one way of dealing with int and one way of dealing with void*. With a policy, you can define at the exact granularity that you want how exactly your handle maps to a type and how it is manipulated - and that policy will be part of the object type. I'm not sure that the inheritance-based approach is superior or not, it sure would be worth some discussion. For more reference on traits, here are two articles that might be of relevance: http://www.moderncppdesign.com/publications/traits.html http://www.moderncppdesign.com/publications/traits_on_steroids.html Andrei ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Gregory Colvin [EMAIL PROTECTED] writes: I'm generally less afraid of automatic conversions than many others, and dropped them from auto_ptr, and later from shared_ptr, only under duress. I like them for wrapper classes because they make it possible to drop the wrappers directly into existing code that uses the wrapped types. I like the terseness too, but then I am perverse enough to prefer *p to p.get(). Some conversions are worse than others. For example, an implicit conversion from a raw pointer to an owning handle/smart-pointer is far more dangerous than the opposite conversion. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
On Tuesday, Jul 22, 2003, at 05:56 America/Denver, David Abrahams wrote: Gregory Colvin [EMAIL PROTECTED] writes: I'm generally less afraid of automatic conversions than many others, and dropped them from auto_ptr, and later from shared_ptr, only under duress. I like them for wrapper classes because they make it possible to drop the wrappers directly into existing code that uses the wrapped types. I like the terseness too, but then I am perverse enough to prefer *p to p.get(). Some conversions are worse than others. For example, an implicit conversion from a raw pointer to an owning handle/smart-pointer is far more dangerous than the opposite conversion. Agreed. It is the latter conversions I like. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Gregory Colvin [EMAIL PROTECTED] writes: Some conversions are worse than others. For example, an implicit conversion from a raw pointer to an owning handle/smart-pointer is far more dangerous than the opposite conversion. Agreed. It is the latter conversions I like. That said, I'm pretty sure I remember that there was a case from Howard which killed the appeal for me. This was a long time ago, just around when the conversion was removed from the Boost shared_ptr. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Gennadiy Rozental [EMAIL PROTECTED] wrote: I read all of the previous discussion of this on the boost list and did not find any good arguments against mine. 1) Pointer specific features have been removed for smart_handle. Both implicit and explicit type coercion features are gone as are operators * and -. I do not see anything wrong with operator* and operator-. How are you going to provide an access to the handle value? operator* as good as anything else for this purpose. How are you going to provide an access to methods that handle type may expose. operator- as good (if not best) way to do so. get() is used to access the handle value. Handles don't expose any methods so operator- is a non-starter. operator* could be used to access the handle value, but I don't see what the advantage to that is. 2) Rather than taking the handle type as a template parameter, smart_handle classes take a handle policy (or traits class or description class or whatever the correct term is). PBSP could do the same. (2) is designed to deal with the fact that the actual type of a handle rarely uniquely identifies the handle type PBSP could do the same. - Not all handles are pointers (e.g., file descriptors) and thus cannot be used with smart_ptrs PBSP would cover everything. I should say that many of these arguments I was making was against using the existing Boost smart_ptr classes for handle management. I agree that a policy based smart pointer could be designed that would do all of the things you say, but I'll give reasons below why I don't think that's a good idea. - Semantically, handles simply aren't pointers. E.g, the pointer deference operators make no sense for handles. Again it's your point of view. I have different. and PBSP could prohibit usage of operator* if you like so. This may be something that we will never agree on, but I'll try to give fuller reasons for my point of view. First, here is what I see as the similariies between handles and pointers. In some, but not all, cases in C++, pointers serve as handles to a key resource -- namely, memory. Operator new is the resource acquisition function and operator delete is the release function. The difference is that pointers are a language construct while other handles (e.g., file descriptors, FILE*s, etc) are not. The standard specifies detailed and often nuanced semantics for pointers and their interaction with the type system. None of this applies to API based handles which serve only as chits or markers to be handed back to the API to identify the resource in question. I suppose that where we differ is that you think the similarity is enough to justify unifying the management of both pointers and handles in a single component, whereas I don't. [snip] I listed all you reasons. None seems to be sound enough to justify yet another component that mimics smart pointer concept. Whatever you do you will end up with either limited functionality or slightly cut version of PBSP (IMHO). That is why I stick with the my PBSP and use it for all my smart pointer needs. I can only repeat that pointers are not handles. You seem to be describing a policy based resource management class. I think this is too broad. I agree that the smart handle classes I've proposed have limited functionality. That's the idea. I also think that's what makes them worthwhile. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Anthony Liguori [EMAIL PROTECTED] wrote: Being primarily a Unix developer, I think this library could have a great use in Unix as long as it can do a few things. Namely, it needs to be flexible enough to deal with C style inherent (i.e. it should allow for custom features for socket type but I should also be able to use file descriptor features for that same type since a socket is a file descriptor). I think a policy based design would be interesting to pursue here. I'm glad it looks useful to you. I've addressed some of these points below. [snip] struct win_file_handle { typedef HANDLE handle_type; static bool is_valid(handle_type h) { return h != INVALID_HANDLE_TYPE; } static void release(handle_type h) { if (is_valid(h)) ::CloseHandle(h); } static handle_type default_value() { return INVALID_HANDLE_TYPE; } static bool equal(handle_type lhs, handle_type rhs) { return lhs==rhs; } }; typedef scoped_handlewin_file_handle scoped_win_file_handle; This type would be unrelated to, for example, a Windows HBITMAP, although both HANDLE and HBITMAP are void*s. But the above would be valid for HBITMAPs since what you're declare is really only specific to HANDLEs. an win_bitmap_handle traits class would be identical to the above wouldn't? So should I just typedef win_file_handle win_bitmap_handle? Then we're back to square 1. HBITMAP uses a different release method, but that's not too important. Even two handles that are of logically different types, but whose traits classes are identical, could be easily distinguished by the type system using inheritance. For example, struct win_handle { /* all members as above */ }; struct win_file_handle : win_handle {}; struct win_file_mapping_handle : win_handle {}; scoped_handlewin_file_handle and scoped_handlewin_file_mapping_handle are completely unrelated types now. This also saves quite a bit of typing, which people seem to be big fans of. - Semantically, handles simply aren't pointers. E.g, the pointer deference operators make no sense for handles. But if you think of think of a smart handle as a container containing a C type, then it makes a little more sense. Perhaps, but operator- still makes no sense. The biggest problem is that for win_file_handle for example, it's probably almost as easy to just implement a wrapper class that provides a constant interface than to use smart_handles. The traits class is very straightforward and trivial to implement -- much more so than a full handle wrapper in my opinion. Further, much of the redundancies can be eliminated by inheritance as in the above example. I like the initial implementation. I've included a small sample of a similiar class as a proof-of-concept of adapting smart_handle to be a little more flexible and easier to use. The main differences are: - A policy based design to whereas the policy extends the classes interface. - Stronger typing (the types are different based on typename, not on traits). The traits approach seems fundamentally flawed as two separate types could share the same traits. I think that the traits system makes the typing stronger. It guarantees distinct types even in the face of handles that are otherwise indistinguishable. I looked at your design, but I think I can handle what you're trying to do through traits class inheritance. I don't see any use to extending the interface through a policy class. Let me know if I've missed something. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin [EMAIL PROTECTED] wrote: Inline. John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] If you can convince most of the people on this list to provide an automatic conversion, more power to you. I still maintain that avoiding hard to diagnose errors is worth much more than saving 6 characters of typing. I am not trying to convince anybody in overall goodness of automatic conversion. :-) I am asking question, which is still ignored: what hard to diagnose errors do you envision for smart handles??? Reference to some dogma would suffice too. ;-) For a discussion of why user defined conversions are a bad idea (not always, but most of the time), see More Effective C++, Item 5. I've read it when it was printed. I know author's reasons. And I agree with most of them. The question is: how do they apply in _this particular case_? I am not ignoring the question. The point is that it is hard to guess what errors might occur. I did reference some dogma as well. I take Meyers' point to be that automatic conversions can sometimes produce surprising effects. Those effects may result in code that does something other than what it appears to do. Thus, *unless there is a very good reason*, avoid automatic conversions. That is what I did. Your reason for including them, i.e., avoiding typing, does not strike me as a good one. John P.S. Of course, if you want Scott Meyers on your side in this one, just look at Item 9 in the same book, where he does exactly what you're suggesting :-). Against his own better judgment IMHO. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
I'm generally less afraid of automatic conversions than many others, and dropped them from auto_ptr, and later from shared_ptr, only under duress. I like them for wrapper classes because they make it possible to drop the wrappers directly into existing code that uses the wrapped types. I like the terseness too, but then I am perverse enough to prefer *p to p.get(). On Monday, Jul 21, 2003, at 22:27 America/Denver, John Madsen wrote: Eugene Lazutkin [EMAIL PROTECTED] wrote: Inline. John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] If you can convince most of the people on this list to provide an automatic conversion, more power to you. I still maintain that avoiding hard to diagnose errors is worth much more than saving 6 characters of typing. I am not trying to convince anybody in overall goodness of automatic conversion. :-) I am asking question, which is still ignored: what hard to diagnose errors do you envision for smart handles??? Reference to some dogma would suffice too. ;-) For a discussion of why user defined conversions are a bad idea (not always, but most of the time), see More Effective C++, Item 5. I've read it when it was printed. I know author's reasons. And I agree with most of them. The question is: how do they apply in _this particular case_? I am not ignoring the question. The point is that it is hard to guess what errors might occur. I did reference some dogma as well. I take Meyers' point to be that automatic conversions can sometimes produce surprising effects. Those effects may result in code that does something other than what it appears to do. Thus, *unless there is a very good reason*, avoid automatic conversions. That is what I did. Your reason for including them, i.e., avoiding typing, does not strike me as a good one. John P.S. Of course, if you want Scott Meyers on your side in this one, just look at Item 9 in the same book, where he does exactly what you're suggesting :-). Against his own better judgment IMHO. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
Alan Bellingham [EMAIL PROTECTED] writes: did they give you the name of this library? Presumably this is WTL - the Windows Template Library. That's the one. -- I've used it and it's great! I hated MFC for a long time, WTL is indeed cool! And as far as I know it's developed by 3 people that work at Microsoft. It really gives you a lot of freedom - at combining what features you want (resizability, message filtering, etc.) Best, John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Gregory Colvin [EMAIL PROTECTED] writes: On Saturday, Jul 19, 2003, at 20:52 America/Denver, Ross Smith wrote: On Sunday 20 July 2003 11:46, Gregory Colvin wrote: There are no Powers That Be. Boost has no policy-based smart pointers because nobody has done the difficult job of proposing them. Now that is simply a barefaced lie. I proposed one myself, which got roundly ignored, and there have been several others. Excuse me. By propose I meant a formal proposal, not just a posting. Furthermore, far from ignoring postings on PBSP, I for one invested considerable time in discussing exception safety issues with one guy working on it. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Inline. John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] If you can convince most of the people on this list to provide an automatic conversion, more power to you. I still maintain that avoiding hard to diagnose errors is worth much more than saving 6 characters of typing. I am not trying to convince anybody in overall goodness of automatic conversion. :-) I am asking question, which is still ignored: what hard to diagnose errors do you envision for smart handles??? Reference to some dogma would suffice too. ;-) For a discussion of why user defined conversions are a bad idea (not always, but most of the time), see More Effective C++, Item 5. I've read it when it was printed. I know author's reasons. And I agree with most of them. The question is: how do they apply in _this particular case_? Thanks, Eugene ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Inline, John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] The main uses of the library as I see it is to handle two main cases: 1) Where a programmer needs to access an API (whether it be from the OS or a 3rd party C API) which uses handle-based resource management and for which not suitable C++ wrapper exists. 2) As an aid in implementing C++ wrapper classes for APIs mentioned in (1). It looks like reasonable goal. Personally I found that there are two cases: 1) If there is large existing API = use smart handles. In this case smart handle serves two purposes: a) provides invisible housekeeping (like destruction of underlying handle) b) behaves like regular handle to be easily used with existing API 2) If existing API is compact = use functional wrapper. Smart handle may be used as part of such wrapper. Example for #1. Windows GDI has hundreds (if not thousands) API functions. New versions of Windows introduce new API functions. It doesn't make any sense to cover it with functional wrapper. MFC tried it and failed. Example for #2. Synchronization primitives in Windows are represented by handles as well. API is compact (~5 functions per primitive). Additional problem is almost all synchronization primitives are represented by generic HANDLE. In this case it makes sense to use functional wrapper instead of smart handle. I have little experience with X-Windows, so I can't comment on that. However, there is absolutely *nothing* in the smart_handle library that is platform specific. Just because one of the most obvious cases where it is useful is a specific platform, does not make the library itself platform specific. I find COM can be touted as platform independent standard but in 99.99% of case it is used on Windows. Looks very windowsy to me. ;-) We can have any proprietary stuff dressed as platform independent. In best case such masquerade would fool us into thinking that it is more than it is. In worst case it would be clumsy to use for proprietary stuff and unusable for anything else. it hard to believe that there is no other C API which uses handles for resource management that doesn't have a suitable C++ wrapper for every case other than Windows. Usually solution and problem go in pair. And problem goes before solution. In this case solution is our response to problem. Well, your comment tells me that we have a solution in search of a problem. Not that there's anything wrong with that. Six characters (.get()) doesn't seem cumbersome to me and seems much better than a conversion operator which for many reasons is frowned upon. Note also It all depends on who you ask. Some people are 100% sure that multiple inheritance == bad design in 100% cases. Some people hate virtual inheritance. Some people think that OOP is sooo 60s. Some people think that generic programming should be banned. I say: look at the problem and use what is more appropriate. that auto_ptr and the like provide those operators so that they can actually act like pointers. If you want the pointer value itself from an auto_ptr, you call get(). Note also that std::string has c_str() rather than operator const char*(). Using operator-() and operator*() you use pointer value itself. It is pretty rare situation when you need it directly and not as part of abc-def() or *abc constructs. Example of c_str() is irrelevant --- you can do all string manipulations without c_str(). The former is needed to interface legacy systems, which is not frequent case. Auto_ptr was modeled after regular pointer. That is why it is so simple to use. It provides a) invisible housekeeping (see beginning of post) and b) has pointer-like API. In most cases it can be used as drop-in replacement in existing code. I think smart handle should be done using exactly the same philosophy. Invisible housekeeping clause stands. And handle-like API is ... seamless conversion. What are real downsides of that? I agree that in many cases scoped is more useful. However, it was fairly trivial to do shared and weak, so I figured why not? Also, shared_handles will work in stl containers while scoped_handles will not. Isn't it an overkill to use reference counting to put handles in vector? Is it the best solution for such problem? :-) Thanks, Eugene ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Inline. Jon Biggar [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] For example, on UNIX, to securely create a file, you need to use the O_CREAT and O_EXCL flags to ensure that nobody else created the file first and is just waiting for you to write to it so they can read what you wrote. (There are other ways of circumventing naive security that are similar.) Isn't it classic example on IPC: synchronization, classic readers-writers problem? Well, it appears everything can be solved using files. :-) The C++ I/O library does not give the programmer the ability to set those flags, so raw file descriptors or FILE * (using fdopen()) are the only solution to the problem. It looks like this kind of problem should be handled by ISO C++ committee. It would be more radical solution than using smart handle to accomplish that. Another possibility is interfacing to a legacy C library. Which one? Is it in wide use? Could you name it? Maybe the best way to deal with this legacy C library is to provide a functional wrapper. Another example is UNIX sockets network programming. It looks like every college uses C++ sockets as an exercise for Comp.Sci. students. I thought this problem was solved long time ago. Last time I checked I found numerous implementations. None of them used smart handle as ultimate solution. All of them were functional wrappers. Hmm, what does Google say about it now? And I hate to anger professors leaving students without proper exercise. :-) Thanks, Eugene ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin [EMAIL PROTECTED] writes: It looks like reasonable goal. Personally I found that there are two cases: 1) If there is large existing API = use smart handles. In this case smart handle serves two purposes: a) provides invisible housekeeping (like destruction of underlying handle) b) behaves like regular handle to be easily used with existing API 2) If existing API is compact = use functional wrapper. Smart handle may be used as part of such wrapper. Example for #1. Windows GDI has hundreds (if not thousands) API functions. New versions of Windows introduce new API functions. It doesn't make any sense to cover it with functional wrapper. MFC tried it and failed. How do you measure failure? Certainly MFC is primitive, but tens of thousands of developers use it every day. There are better alternatives - Microsoft tells me they have been shipping an unsupported library which is what MFC would have been if we'd started with templates. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Hi, I do not want to start this discussion all over again, but in the reasoning you presenting I did not find anything new to justify another smart pointer like component. It's only one simple case of PBSP and I do not see any reason not to use it. Gennadiy. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
How do you measure failure? Certainly MFC is primitive, but tens of thousands of developers use it every day. There are better alternatives - Microsoft tells me they have been shipping an unsupported library which is what MFC would have been if we'd started with templates. did they give you the name of this library? -- Dave Abrahams Boost Consulting www.boost-consulting.com Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: There oughta be a law ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
Victor A. Wagner Jr.: How do you measure failure? Certainly MFC is primitive, but tens of thousands of developers use it every day. There are better alternatives - Microsoft tells me they have been shipping an unsupported library which is what MFC would have been if we'd started with templates. did they give you the name of this library? Presumably this is WTL - the Windows Template Library. url:http://www.microsoft.com/downloads/details.aspx?familyid=128e26ee-2112-4cf7-b28e-7727d9a1f288displaylang=en Overview Windows Template Library (WTL) is a library for developing Windows® applications and UI components. It extends ATL (Active Template Library) and provides a set of classes for controls, dialogs, frame windows, GDI objects, and more. This version provides full support for Visual Studio .NET and Windows XP. Note: The Windows Template Library (WTL) is not supported by Microsoft Product Support Services. However, you may find some peer support at the WTL Support List Web site. Despite the unsupported nature, it's currently at version 7.0 When they mention templates, they certainly went far beyond MFC - ATL not only uses multiple inheritance, it even use the Curiously Recurring Template Pattern. Having said which, any further discussion is probably off topic, unless we're trying to learn lessons from its design to apply to Boost candidates. Alan -- Alan Bellingham ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Alan Bellingham [EMAIL PROTECTED] writes: did they give you the name of this library? Presumably this is WTL - the Windows Template Library. That's the one. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin [EMAIL PROTECTED] wrote: Inline, John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] I have little experience with X-Windows, so I can't comment on that. However, there is absolutely *nothing* in the smart_handle library that is platform specific. Just because one of the most obvious cases where it is useful is a specific platform, does not make the library itself platform specific. I find COM can be touted as platform independent standard but in 99.99% of case it is used on Windows. Looks very windowsy to me. ;-) We can have any proprietary stuff dressed as platform independent. In best case such masquerade would fool us into thinking that it is more than it is. In worst case it would be clumsy to use for proprietary stuff and unusable for anything else. I fail to see how COM is a relevant analogy. The smart_handle classes I've proposed will work on all major platforms unlike COM. Several people have already suggested that it would be worthwhile for FILE*s and file descriptors. it hard to believe that there is no other C API which uses handles for resource management that doesn't have a suitable C++ wrapper for every case other than Windows. Usually solution and problem go in pair. And problem goes before solution. In this case solution is our response to problem. Well, your comment tells me that we have a solution in search of a problem. Not that there's anything wrong with that. See point above. that auto_ptr and the like provide those operators so that they can actually act like pointers. If you want the pointer value itself from an auto_ptr, you call get(). Note also that std::string has c_str() rather than operator const char*(). Using operator-() and operator*() you use pointer value itself. It is pretty rare situation when you need it directly and not as part of abc-def() or *abc constructs. Example of c_str() is irrelevant --- you can do all string manipulations without c_str(). The former is needed to interface legacy systems, which is not frequent case. Automatic conversions are well known sources of hard to find bugs. Six characters hardly seems like a big deal. Auto_ptr was modeled after regular pointer. That is why it is so simple to use. It provides a) invisible housekeeping (see beginning of post) and b) has pointer-like API. In most cases it can be used as drop-in replacement in existing code. I think smart handle should be done using exactly the same philosophy. Invisible housekeeping clause stands. And handle-like API is ... seamless conversion. What are real downsides of that? I agree that in many cases scoped is more useful. However, it was fairly trivial to do shared and weak, so I figured why not? Also, shared_handles will work in stl containers while scoped_handles will not. Isn't it an overkill to use reference counting to put handles in vector? Is it the best solution for such problem? :-) Not necessarily. Please suggest another. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Gennadiy Rozental [EMAIL PROTECTED] wrote: Hi, I do not want to start this discussion all over again, but in the reasoning you presenting I did not find anything new to justify another smart pointer like component. It's only one simple case of PBSP and I do not see any reason not to use it. Please tell me where my reasoning is incorrect (I would genuinely like to know). I read all of the previous discussion of this on the boost list and did not find any good arguments against mine. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Inline David Abrahams [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Example for #1. Windows GDI has hundreds (if not thousands) API functions. New versions of Windows introduce new API functions. It doesn't make any sense to cover it with functional wrapper. MFC tried it and failed. How do you measure failure? Certainly MFC is primitive, but tens of It is a Boolean function --- pass/fail. :-) Take a look at wrapped handles in, say, afxwin. You will find a lot of marvels of object-oriented code like this: ... _AFXWIN_INLINE COLORREF CDC::GetBkColor() const { ASSERT(m_hAttribDC != NULL); return ::GetBkColor(m_hAttribDC); } _AFXWIN_INLINE int CDC::GetBkMode() const { ASSERT(m_hAttribDC != NULL); return ::GetBkMode(m_hAttribDC); } _AFXWIN_INLINE int CDC::GetPolyFillMode() const { ASSERT(m_hAttribDC != NULL); return ::GetPolyFillMode(m_hAttribDC); } _AFXWIN_INLINE int CDC::GetROP2() const { ASSERT(m_hAttribDC != NULL); return ::GetROP2(m_hAttribDC); } _AFXWIN_INLINE int CDC::GetStretchBltMode() const { ASSERT(m_hAttribDC != NULL); return ::GetStretchBltMode(m_hAttribDC); } _AFXWIN_INLINE COLORREF CDC::GetTextColor() const { ASSERT(m_hAttribDC != NULL); return ::GetTextColor(m_hAttribDC); } _AFXWIN_INLINE int CDC::GetMapMode() const { ASSERT(m_hAttribDC != NULL); return ::GetMapMode(m_hAttribDC); } ... Majority of methods are like that. I call this style of OOP failure in large part because it doesn't make much sense to me. What is the point of replacing XXX(a) with a.XXX()? It is all done so you can program your graphics in cool way (pseudo code): CDC dc; ... { CPen pen( PS_SOLID, 0, RGB(0,0,0) ); CBrush brush( RGB(255,255,255) ); CPen* old_pen = dc.SelectObject(pen); CBrush* old_brush = dc.SelectObject(brush); dc.Rectangle( 0, 0, 100, 100 ); dc.SelectObject(old_brush); dc.SelectObject(old_pen); } ... Compare it with boring old code: HDC dc = NULL; ... HPEN pen = CreatePen( PS_SOLID, 0, RGB(0,0,0) ); HBRUSH brush = CreateSolidBrush( RGB(255,255,255) ); HGDIOBJ old_pen = SelectObject( dc, pen ); HGDIOBJ old_brush = SelectObject( dc, brush ); Rectangle( dc, 0, 0, 100, 100 ); SelectObject( dc, old_brush ); SelectObject( dc, old_pen ); ... Added value of MFC methods (functionally) is close to nothing. Almost the same amount of characters to type. Of course, CDC methods have asserts in them and can help you to debug a code. Another notable difference is handle destruction. In my example I didn't do it (two extra lines of code): DeleteObject(brush); DeleteObject(pen); This difference is the only reason for me why MFC wrappers are useful. Now imaging that we use simple smart handles for HDC, HPEN, and HBRUSH. Let's call them Dc, Pen, and Brush respectively. These smart handles provides housekeeping by calling appropriate functions in destructor and (just like MFC) operator Handle(). All of them would be about ten lines of code (pseudo code to give an idea): struct Pen { explicit Pen( HPEN h ) : hp(h) {} ~Pen() { DeleteObject(hp); } operator HPEN () const { return hp; } operator HGDIOBJ () const { return hp; } HPEN hp; } Additionally let's introduce SafeSelectObject (pseudo code): struct SafeSelectObject { SafeSelectObject( HDC h, HGDIOBJ obj ) : hDC(h), old_handle( ( h obj ) ? SelectObject( h, obj ) : NULL ) {} ~SafeSelectObject() { if( hDC old_handle ) SelectObject( hDC, old_handle ); } HDC hDC; HGDIOBJ old_handle; }; Now our example looks like this: Dc dc; ... { Pen pen( CreatePen( PS_SOLID, 0, RGB(0,0,0) ) ); Brush brush( CreateSolidBrush( RGB(255,255,255) ) ); SafeSelectObject old_pen( dc, pen ); SafeSelectObject old_pen( dc, brush ); Rectangle( dc, 0, 0, 100, 100 ); } ... Hey, it looks like MFC! Almost. The difference? I didn't write _huge_ classes like CDC --- I tend to think that class with hundred methods is bad idea. These handles support all GDI functions including new ones like exotic AlphaBlend() or GradientFill(). If you want to do asserts on your handles like MFC does, you can do it in conversion operator. Now I think you understand my point. thousands of developers use it every day. There are better Count me in. :-) alternatives - Microsoft tells me they have been shipping an unsupported library which is what MFC would have been if we'd started with templates. WTL? ;-) Please understand me correctly. I am not trying to prove that MFC is evil. :-) Given its historical background and necessity to support legacy versions, probably it is as good as it can be. Of course, we should not forget that MFC is _much_ more than collection of simple handle wrappers. But I don't want our smart handles to be done in MFC way. Please note that in exercise above I didn't use any new C++ features, which were not available back in 1992. I didn't even use templates! But provided functionality is pretty much similar. :-)) Thanks, Eugene ___ Unsubscribe other changes:
[boost] Re: Proposed smart_handle library
Inline. John Madsen [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] I fail to see how COM is a relevant analogy. The smart_handle classes I've proposed will work on all major platforms unlike COM. Several people have COM was available on all major platforms. I still remember running it on Solaris and HP-UX (?) long time ago. already suggested that it would be worthwhile for FILE*s and file descriptors. I am not in position to judge their reasons --- I never had this need. Maybe I avoided their specific problems somehow. Or these problems are not frequent enough. Anyway, I can speak only for myself. And I am not convinced yet. :-) Usually solution and problem go in pair. And problem goes before solution. In this case solution is our response to problem. Well, your comment tells me that we have a solution in search of a problem. Not that there's anything wrong with that. See point above. Hmm. I expected that _you_ will tell in your proposal something like that: There is this huge set of problems. These are specific examples majority of programmers are struggling with frequently. (Stone cold facts and examples). And this is how I propose to change our hard life to the better. (Solution). :-) Something like that. Instead you proposed solution without proofs of problem. I guess I had wrong expectations. Automatic conversions are well known sources of hard to find bugs. Six In all cases? Well, programming itself is well known source of hard to find bugs. :-) I don't think that this is valid argument in this particular case. characters hardly seems like a big deal. And still nobody uses auto_ptr like this: p.get()-XXX(). :-) If we can simplify our life, we should. If we can save 1 character in frequently used idiom, we should. Isn't it an overkill to use reference counting to put handles in vector? Is it the best solution for such problem? :-) Not necessarily. Please suggest another. I have some ideas how to deal with this problem. But all of them fall outside of discussion about smart handles. Thanks, Eugene ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin [EMAIL PROTECTED] wrote: Inline. already suggested that it would be worthwhile for FILE*s and file descriptors. I am not in position to judge their reasons --- I never had this need. Maybe I avoided their specific problems somehow. Or these problems are not frequent enough. Anyway, I can speak only for myself. And I am not convinced yet. :-) That's fine, but I was responding to your point that smart_handle is platform specific to Windows. I think I've provided ample evidence that it isn't. Usually solution and problem go in pair. And problem goes before solution. In this case solution is our response to problem. Well, your comment tells me that we have a solution in search of a problem. Not that there's anything wrong with that. See point above. Hmm. I expected that _you_ will tell in your proposal something like that: There is this huge set of problems. These are specific examples majority of programmers are struggling with frequently. (Stone cold facts and examples). And this is how I propose to change our hard life to the better. (Solution). :-) Something like that. Instead you proposed solution without proofs of problem. I guess I had wrong expectations. I'm not sure how stone cold they are, but I mentioned Windows' handles, file descriptors, and FILE*s in my original message. Automatic conversions are well known sources of hard to find bugs. Six In all cases? Well, programming itself is well known source of hard to find bugs. :-) I don't think that this is valid argument in this particular case. characters hardly seems like a big deal. And still nobody uses auto_ptr like this: p.get()-XXX(). :-) If we can I was never suggesting that anyone used auto_ptr like this. simplify our life, we should. If we can save 1 character in frequently used idiom, we should. If you can convince most of the people on this list to provide an automatic conversion, more power to you. I still maintain that avoiding hard to diagnose errors is worth much more than saving 6 characters of typing. For a discussion of why user defined conversions are a bad idea (not always, but most of the time), see More Effective C++, Item 5. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin [EMAIL PROTECTED] wrote: I have a few comments in no particular order. 1) I cannot imaging someone programming in C++ and using FILE*s,and file descriptors instead of iostream Co. You've must be talking about incomplete systems like embedded systems, which don't have complete standard C++ library. Are there any real life examples for that? How frequent are they? That's quite right. I don't see much use in having a wrapper for FILE*. File descriptors' are a different story. Two cases that jump to mind are memory mapped files and socket descriptors. In neither case are there general purpose cross platform C++ libraries (that I'm aware of) that eliminate any reasonable need to deal with file descriptors for these purposes. The main uses of the library as I see it is to handle two main cases: 1) Where a programmer needs to access an API (whether it be from the OS or a 3rd party C API) which uses handle-based resource management and for which not suitable C++ wrapper exists. 2) As an aid in implementing C++ wrapper classes for APIs mentioned in (1). 2) Windows handles are problem indeed because they are not covered by standard libraries. MFC covers it but being a behemoth it is not suitable for some applications. ATL is better but it doesn't address handle issue. A lot of people and their grandma have created their own home-brewed handle wrappers. Yes, one of purposes is to make this easier and to provide a semi-standard interface. 2a) You are not entirely correct in assumption that Most Windows' handles are actually void pointers. For years Microsoft uses so called strict definitions by default (you have to switch to old mode explicitly). This is relevant code from their headers for illustration purposes: [code snipped] As you can see HANDLE is void* but almost all other handles declared using DECLARE_HANDLE() macro, which makes them of different types. Notable exception is HGDIOBJ, which is void* as well. The former was done to facilitate inheritance-like relationship between generic GDI handle (HGDIOBJ) and specialized GDI handles (HPEN, HBRUSH, HFONT, HRGN, and so on) with C compiler. I was unaware that this was now the default. However, the importance of the RAII aspects of smart_handle still stand. 2b) It appears to me that Windows handles and their profound importance are quite unique. I never struggled with something like that on X Window, for example. If this is the case, we are talking about platform-specific solution. I am not sure Boost is right place for platform-specific libraries. Of course, it is possible to make such library platform-independent but is it going to be used outside of Windows world? I have little experience with X-Windows, so I can't comment on that. However, there is absolutely *nothing* in the smart_handle library that is platform specific. Just because one of the most obvious cases where it is useful is a specific platform, does not make the library itself platform specific. I find it hard to believe that there is no other C API which uses handles for resource management that doesn't have a suitable C++ wrapper for every case other than Windows. 3) Necessity to call get() method every time you need to use handle is cumbersome. That's why auto_ptr or any other smart pointers define operator-() and operator*(). Instead of these operators smart_handle should define operator Handle() (where Handle is underlying handle type). Six characters (.get()) doesn't seem cumbersome to me and seems much better than a conversion operator which for many reasons is frowned upon. Note also that auto_ptr and the like provide those operators so that they can actually act like pointers. If you want the pointer value itself from an auto_ptr, you call get(). Note also that std::string has c_str() rather than operator const char*(). 4) Sometimes destruction of handles is more than a simple call to one-argument procedure. Real example from Windows, which is encountered frequently: HDC hDC = GetDC(hWindow); // do some drawing... ReleaseDC( hWindow, hDC ); In this example destruction (releasing) involves some kind of context (window handle). Apparently it is not handled by proposed library. Thanks for this example. I had not considered cases like this and will think more about it. 5) While I frequently needed scoped handles, I never encountered real need to have weak handles and reference-counted handles. When I wanted to do something like that, I created object, which was handled by smart pointer of some kind. Admittedly this is not light weight solution but it was never a bottleneck in my projects. Scoped handles are used extensively a should be as light weight as possible. I agree that in many cases scoped is more useful. However, it was fairly trivial to do shared and weak, so I figured why not? Also, shared_handles will work in stl containers while scoped_handles will not. Thanks, Eugene PS: Yeah, I am one of
[boost] Re: Proposed smart_handle library
Larry Evans [EMAIL PROTECTED] wrote: wouldn't deadlock detection be another application? Taking the definition directly from my long-ago OS course memory, a deadlock occurs when one task or process holds a handle to a lock on a resource required by another task, which in turn, holds another handle to a lock on another resource required by first task. If a task cannot acquire the resource after a certain amount of time, it might try to find whether another task is holding that resource. Now, if all the handles record their location in memory using Detlef's method for smart pointers (and implemented in boost files under shared_cyclic_ptr), wouldn't this make it possible for a task to do this? I haven't looked much at the cyclic pointer classes, so I'm not sure exactly how this would work in the cases of handles. My inclination, though, is that this issue would be better addressed in the thread library. I had in mind that smart_handle would perform a fairly simple task across a very wide variety of handles. For many of those handle types deadlock detection doesn't make any sense. Perhaps, though, I'm missing the point entriely. John ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
On Friday, Jul 18, 2003, at 15:21 America/Denver, John Madsen wrote: Eugene Lazutkin [EMAIL PROTECTED] wrote: I have a few comments in no particular order. 1) I cannot imaging someone programming in C++ and using FILE*s,and file descriptors instead of iostream Co. You've must be talking about incomplete systems like embedded systems, which don't have complete standard C++ library. Are there any real life examples for that? How frequent are they? That's quite right. I don't see much use in having a wrapper for FILE*. IMHO stdio is a useful standard, and for some purposes is better than iostreams. Of course, boost::shared_ptr can already wrap FILE* pretty easily. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposed smart_handle library
On Saturday 19 July 2003 09:21, John Madsen wrote: Eugene Lazutkin [EMAIL PROTECTED] wrote: 4) Sometimes destruction of handles is more than a simple call to one-argument procedure. Real example from Windows, which is encountered frequently: HDC hDC = GetDC(hWindow); // do some drawing... ReleaseDC( hWindow, hDC ); In this example destruction (releasing) involves some kind of context (window handle). Apparently it is not handled by proposed library. Thanks for this example. I had not considered cases like this and will think more about it. This is easily handled; just use boost::bind(ReleaseDC, hWindow, _1) for the release function. -- Ross Smith . [EMAIL PROTECTED] . Auckland, New Zealand As Unix guru types go, I'm sweet, patient, and comprehensible. Unfortunately, Unix guru types don't go very far in that direction. I used to think this was a personality flaw. -- Elizabeth Zwicky ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Proposed smart_handle library
Eugene Lazutkin wrote: I have a few comments in no particular order. 1) I cannot imaging someone programming in C++ and using FILE*s,and file descriptors instead of iostream Co. You've must be talking about incomplete systems like embedded systems, which don't have complete standard C++ library. Are there any real life examples for that? How frequent are they? Imagine again. :) For example, on UNIX, to securely create a file, you need to use the O_CREAT and O_EXCL flags to ensure that nobody else created the file first and is just waiting for you to write to it so they can read what you wrote. (There are other ways of circumventing naive security that are similar.) The C++ I/O library does not give the programmer the ability to set those flags, so raw file descriptors or FILE * (using fdopen()) are the only solution to the problem. Another possibility is interfacing to a legacy C library. Another example is UNIX sockets network programming. -- Jon Biggar Floorboard Software [EMAIL PROTECTED] [EMAIL PROTECTED] ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost