Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 15:00 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: Also, if shared_ptr only needs to allocate at construction time (I'm not sure of this) we can avoid storing the allocator at all. Then how to deallocate? Using the custom deleter? Which will need to store a copy of the allocator, unless one takes advantage of the weasel wording that lets you instantiate a new one for the purpose. ... It still doesn't make any sense to return a T* from allocate since normally with a non-singular T* p, either p == 0 or *p refers to a constructed T. The idea was that Allocator::pointer might be a proxy type that cannot be converted to void* and back, so allocate() must return and construct() must take an Allocator::pointer rather than a void*. Wow, creepy. Yes. But unless you grant the desire to support such creepy beasts then not much of Allocator makes any sense. And such beasts can do useful work, like persistent stores and shared memory. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 13:18 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: Yep. I still think UserAllocator is a good default, and that where it doesn't suffice there is some value to playing nicely with STL. So even when we come up with some beautiful new thing to do the allocation job better, we will still need adaptors both ways, so that one can get an allocator from an STL container and turn it in to one of our new things, or take one of our new things and turn it into an allocator to use in an STL container. Am I right in trying to summarize your suggestion about UserAllocator? If you want to parametrize how a boost class manages memory, use UserAllocator parameter. Unless you need the standard Allocator interface. 1. The allocator parameter should implement the UserAllocator interface. 2. All instances of UserAllocator must be equal and stateless. The Boost pools use UserAllocator only as a type parameter. It is not required to be constructible or comparable. 3. If your class is using STL containers, use boost::memory::allocator adapter (see bellow). Why not just use std::allocator? 4. To construct/destroy objects, use boost::memory::construct/destroy. See below. 5. Avoid using explicit references to allocators. ... Usage example: == template< typename T, typename UserAllocator = boost::default_user_allocator_new_delete > class X { What if you want X to use the same allocator as some other STL container constructed with a non-Boost allocator? That would be difficult unless you have template > struct X { X(const StdAllocator&); Also, it might sometimes be desirable, as it is for shared_ptr, to defer the choice of allocator until construction time: template struct X { template > X(const StdAllocator&); Or, if UserAllocator suffices: template struct X { template X(); T* _p; Leading underscores are a no-no. std::vector > _v; X() { _p = boost::memory::construct( 1 ) How to pass arguments to T's constructor? Better just p = new(UserAllocator::malloc(sizeof T)) T(...) } ~X() { if( _p ) boost::memory::destroy( _p, 1 ); In which case, why not just p->~T(), UserAllocator::free(p); ? } }; Eugene ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 12:51 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: On Tuesday, Sep 2, 2003, at 11:22 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: So you would rather use this than use construct? template T* addressof(T& v) { return reinterpret_cast( &const_cast(reinterpret_cast(v))); } As long as it's packaged away and I don't have to look at the implementation. A customization point like an allocator should not be required to supply boilerplate that's always going to be the same. You are assuming that there was no good reason to allow an allocator to hook construct and destroy, for instance to do some bookkeeping. The fact that nobody's required to use construct and/or destroy is testament to that. Thanks to the weasel-wording nobody's required to use much of anything besides allocate, deallocate, and rebind. That doesn't mean there was no point to all the rest in the original design. When I need to find out what I need to implement in order to customize allocation, I don't want to have to read through something which is 50% irrelevant to the task, as the allocator requirements are. Which is why I'm now suggesting that Boost UserAllocator is a better default. But in some cases, like the shared_ptr feature request that got me thinking on this, what you want is just to have objects allocate their internals using the same allocator as the container they are being placed in, in which case you don't need to implement an allocator, just call get_allocator(). Is it enough for all of Boost? It's probably overkill for some things. If so, great! If not, we still need to think about what a more-sophisticated interface looks like. Only if UserAllocator is inadequate? Also, if shared_ptr only needs to allocate at construction time (I'm not sure of this) we can avoid storing the allocator at all. Then how to deallocate? I'm reeling from the implication that the following is undefined behavior for non-POD T: T* p = (T*)malloc(sizeof T); Are you sure? Nope. 3.8/5 shows that I'm wrong. That's a relief. It still doesn't make any sense to return a T* from allocate since normally with a non-singular T* p, either p == 0 or *p refers to a constructed T. The idea was that Allocator::pointer might be a proxy type that cannot be converted to void* and back, so allocate() must return and construct() must take an Allocator::pointer rather than a void*. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 13:00 America/Denver, Peter Dimov wrote: Gregory Colvin wrote: On Tuesday, Sep 2, 2003, at 12:27 America/Denver, Peter Dimov wrote: Then again, the Dinkumware implementation dutifully calls construct and destroy, paying (and forcing me to pay) the abstraction penalty price... so maybe I'm wrong, and construct/destroy are useful? I don't see that there need be any performance price for what Dinkumware does, or is that not what you mean by "abstraction penalty"? I'm not saying that there need be any price in a perfect world. I am saying that in practice, on the compiler I use, there is a price, like calling a non-inline destroy() O(N) times for a value_type that has an inline, empty, nonvirtual destructor. Or even for a built-in value_type. That is most unfortunate. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 12:27 America/Denver, Peter Dimov wrote: Gregory Colvin wrote: You are assuming that there was no good reason to allow an allocator to hook construct and destroy, for instance to do some bookkeeping. I'm curious. Have you ever seen such an allocator? I've always assumed that construct/destroy/pointer are a "but someone might need to do that" feature that nobody has ever used. I've heard allocators described that probably used construct() to navigate efficiently from a proxy pointer to the raw memory in which to construct. But I never saw the code. Then again, the Dinkumware implementation dutifully calls construct and destroy, paying (and forcing me to pay) the abstraction penalty price... so maybe I'm wrong, and construct/destroy are useful? I don't see that there need be any performance price for what Dinkumware does, or is that not what you mean by "abstraction penalty"? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 11:39 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote: ... I think you're missing my point. There's no reason that a stateful allocator should have access to the state data required to allocate U objects, but that's the status quo. I'm probably missing your point, but the idea is that a container needs to allocate various kinds of things, and they all get allocated with the same allocator, either directly or via rebind. For instance, maybe you are are using memory-mapped files as a persistent storage. The Ts and the Us and whatever the container needs all have to go into the same file, so the allocator and all its rebinds must know which file to use and how. ... It's a conceptual mess. Alex didn't have MPL when he invented allocators. So they are messier than they need to be, but I still say they are not so bad as you claim Are you saying my factual claims are wrong, or just that all those issues don't amount to a very important problem? Just that it doesn't look nearly as messy to me as it does to you. and that it would be easier for the next standard to repair them than to replace them. That may be, but we're here at Boost, talking about the interface we should be using in Boost components. Yep. I still think UserAllocator is a good default, and that where it doesn't suffice there is some value to playing nicely with STL. So even when we come up with some beautiful new thing to do the allocation job better, we will still need adaptors both ways, so that one can get an allocator from an STL container and turn it in to one of our new things, or take one of our new things and turn it into an allocator to use in an STL container. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 11:22 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: I think part of my point was that *nobody* needs what they offer, if you include construct/destroy. Or rather that some implementations have failed to use what they offer, and our standard unfortunately doesn't insist that they do. It's not unfortunate if it adds nothing, which is what I believe. Another reason construct is needed is that Allocator::pointer might be a proxy, with operator* and operator-> but not necessarily a conversion to void* or even T*. Doesn't matter; you can always get the address of an object. See http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#390 So you would rather use this than use construct? template T* addressof(T& v) { return reinterpret_cast( &const_cast(reinterpret_cast(v))); } As long as it's packaged away and I don't have to look at the implementation. A customization point like an allocator should not be required to supply boilerplate that's always going to be the same. You are assuming that there was no good reason to allow an allocator to hook construct and destroy, for instance to do some bookkeeping. When I need to find out what I need to implement in order to customize allocation, I don't want to have to read through something which is 50% irrelevant to the task, as the allocator requirements are. Which is why I'm now suggesting that Boost UserAllocator is a better default. But in some cases, like the shared_ptr feature request that got me thinking on this, what you want is just to have objects allocate their internals using the same allocator as the container they are being placed in, in which case you don't need to implement an allocator, just call get_allocator(). n fact, construct requires undefined behavior for non-POD T because you can't copy its T* argument which points into raw storage. I don't understand what you mean by this. Are you claiming that it is undefined to copy just a pointer to raw storage? Unless the pointer has the right type, yes. In which case the A::pointer return from A::allocate() is already undefined behavior? Wow. Yes, IIUC. DR, I guess. I'm reeling from the implication that the following is undefined behavior for non-POD T: T* p = (T*)malloc(sizeof T); Are you sure? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: ... Dave: I think I would rather see a MPL lambda expression or metafunction class interface for allocator type parameters. It makes little sense for the allocator's user to be choosing its value_type. Something like: some_allocator<_1> or struct select_allocator { template struct apply { typedef some_allocator type; }; }; with some_allocator's interface being like what's required for std::allocator but not including misplaced interface bits such as address/construct/destroy, and possibly max_size -- these can be added by a std::allocator facade wrapper if neccessary. I'm not sure we need a simple version and a complicated version. I'm not clear how you intend the above to be used, or what you intend it to be a replacement for. I intend it to be the sort of type parameter that gets passed to our objects which need custom allocation in place of a standard allocator. It's ridiculous, IMO, to pass allocator to a node-based container which is *never* going to allocate a T object. But given rebind() it doesn't really matter. We could just as well have specified that all containers take allocator arguments. The container itself should decide which type the allocator template gets instantiated on, via: mpl::apply, Node>::type [ this is approximately the same as: S::template apply::type == some_allocator except that it works when S is the lambda expression some_allocator<_1> as well as when it's the select_allocator metafunction class below it. ] Sorry, but I'm still not following this, but that may be because I don't know much MPL, so I can only guess at what you are up to. I probably need a detailed example of how to write and use one of these thingys to make any sense of your proposal. Does your proposal support stateful allocators? What the rebind requirement in the allocator means for pool allocation, for example, is that a pool_allocator object must either be stateless (in which case allocator inequality is meaningless) Yes, all stateless allocators compare equal, and stateless allocators are the easiest kind to make compare equal, as the standard currently requires allocators to do. or effectively be able to allocate blocks of *any* size and alignment, rather than just as appropriate for T. Yes, because node-based containers need to allocate nodes, perhaps of various kinds, but they don't expose their node types in their interface. So you have to pass in something, and we went with T rather than void or whatever. It might have been better to have different allocator interfaces for array-based versus node-based containers, since array-based containers have no need of rebind(), and node-based containers have no need of allocator. It's a conceptual mess. Alex didn't have MPL when he invented allocators. So they are messier than they need to be, but I still say they are not so bad as you claim, and that it would be easier for the next standard to repair them than to replace them. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: I think part of my point was that *nobody* needs what they offer, if you include construct/destroy. Or rather that some implementations have failed to use what they offer, and our standard unfortunately doesn't insist that they do. It's not unfortunate if it adds nothing, which is what I believe. Another reason construct is needed is that Allocator::pointer might be a proxy, with operator* and operator-> but not necessarily a conversion to void* or even T*. Doesn't matter; you can always get the address of an object. See http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#390 So you would rather use this than use construct? template T* addressof(T& v) { return reinterpret_cast( &const_cast(reinterpret_cast(v))); } In fact, construct requires undefined behavior for non-POD T because you can't copy its T* argument which points into raw storage. I don't understand what you mean by this. Are you claiming that it is undefined to copy just a pointer to raw storage? Unless the pointer has the right type, yes. In which case the A::pointer return from A::allocate() is already undefined behavior? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Tuesday, Sep 2, 2003, at 05:42 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: On Monday, Sep 1, 2003, at 14:48 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: Conforming containers had better use them. I'm sorry, but I think that's flat wrong. What do you suppose that entry in column 2 of the allocator requirements table (20.1.5) means, after all? It means any value returned by construct, destroy, or deallocate goes unused. And once you are down in the coal mine customizing what a pointer is, I'm not sure you won't need to customize how to construct and destroy. The class getting constructed/destroyed has full control over that or the language is utterly bustificated. Yes, but the allocator may want to do something else as well, and construct and destroy serve as hooks for whatever that may be. Regardless, there is absolutely _nothing_ in the standard AFAICT which indicates the containers must use the allocator's construct and destroy, and several implementations in fact do not. Well then, I consider the standard broken in that regard. But we are off the topic that started this thread. Apropos of which, I now think that the Boost UserAllocator requirements should be the default for components that parameterize how they use memory, with the Standard Allocator requirements being used only for components that need what they offer: a potentially very efficient way to allocate large numbers of small objects of known type, and/or a way to access storage via proxied pointers. I think part of my point was that *nobody* needs what they offer, if you include construct/destroy. Or rather that some implementations have failed to use what they offer, and our standard unfortunately doesn't insist that they do. Another reason construct is needed is that Allocator::pointer might be a proxy, with operator* and operator-> but not necessarily a conversion to void* or even T*. In fact, construct requires undefined behavior for non-POD T because you can't copy its T* argument which points into raw storage. I don't understand what you mean by this. Are you claiming that it is undefined to copy just a pointer to raw storage? If so, then how is placement new not undefined? The standard says: a.construct(p,t) Effect: new((void*)p) T(t) I think I would rather see a MPL lambda expression or metafunction class interface for allocator type parameters. It makes little sense for the allocator's user to be choosing its value_type. Something like: some_allocator<_1> or struct select_allocator { template struct apply { typedef some_allocator type; }; }; with some_allocator's interface being like what's required for std::allocator but not including misplaced interface bits such as address/construct/destroy, and possibly max_size -- these can be added by a std::allocator facade wrapper if neccessary. I'm not sure we need a simple version and a complicated version. I'm not clear how you intend the above to be used, or what you intend it to be a replacement for. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Monday, Sep 1, 2003, at 14:48 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: Conforming containers had better use them. I'm sorry, but I think that's flat wrong. What do you suppose that entry in column 2 of the allocator requirements table (20.1.5) means, after all? It means any value returned by construct, destroy, or deallocate goes unused. And once you are down in the coal mine customizing what a pointer is, I'm not sure you won't need to customize how to construct and destroy. The class getting constructed/destroyed has full control over that or the language is utterly bustificated. Yes, but the allocator may want to do something else as well, and construct and destroy serve as hooks for whatever that may be. Regardless, there is absolutely _nothing_ in the standard AFAICT which indicates the containers must use the allocator's construct and destroy, and several implementations in fact do not. Well then, I consider the standard broken in that regard. But we are off the topic that started this thread. Apropos of which, I now think that the Boost UserAllocator requirements should be the default for components that parameterize how they use memory, with the Standard Allocator requirements being used only for components that need what they offer: a potentially very efficient way to allocate large numbers of small objects of known type, and/or a way to access storage via proxied pointers. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
On Monday, Sep 1, 2003, at 11:31 America/Denver, Joel de Guzman wrote: Fernando Cacciola <[EMAIL PROTECTED]> wrote: vector<>::begin returns an object with operators * and ->, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Huh? pointer semantics (behavior) does not mean that they have to be pointers. But would the following hold if p and q are optionl? *q = 1; p = q; *p = 2; assert(*q == 2); ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Sunday, Aug 31, 2003, at 13:51 America/Denver, Peter Dimov wrote: Gregory Colvin wrote: [...] Two small corrections: shared_ptr currently uses std::allocator to allocate counts regardless. No, it uses plain new/delete by default. It is possible to get it to use std::allocator via a #define. OK. Anyway, the std::allocator interface is adequate for shared_ptr. [...] versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); allocate(1) and deallocate(p, 1) if I'm not mistaken. You are not. I shouldn't post uncompiled code late at night. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Sunday, Aug 31, 2003, at 13:13 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: But indeed allocate/construct/deallocate/destroy is more work than ^^^^ Oyeah. These two absolutely don't belong in allocator, period. Do any implementations even use them? Allocators exist to provide a point of customization for users, but you cannot/should not customize these. Conforming containers had better use them. I'm sorry, but I think that's flat wrong. What do you suppose that entry in column 2 of the allocator requirements table (20.1.5) means, after all? It means any value returned by construct, destroy, or deallocate goes unused. And once you are down in the coal mine customizing what a pointer is, I'm not sure you won't need to customize how to construct and destroy. The class getting constructed/destroyed has full control over that or the language is utterly bustificated. Yes, but the allocator may want to do something else as well, and construct and destroy serve as hooks for whatever that may be. Using allocator is even more work than allocating raw memory with malloc and doing placement new and explicit destruction, then freeing the raw memory. That's my biggest complaint. It's new/delete T* p = new T(); ... delete p; versus malloc/free T* p = (T*)malloc(sizeof T); When you need malloc(sizeof(T) + N) Allocators get a lot harder to use. Agreed. new(p) T(); ... p->~T(); free(p); versus Boost UserAllocator T* p = (T*)user_allocator::malloc(sizeof T); new(p) T(); ... p->~T(); user_allocator::free(p); versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); Oops! There's a pointer missing here. Silly me for not compiling my email. Just a small example of why I'm saying it's a harder interface. Very small. Allocator has strange requirements, like "p shall not be null". Another performance optimization. In most cases there is no way that p could be null in the first place, so why waste time checking? If I need to build a custom one I have to navigate rebind and the implications of allocator inequality for which the standard provides little guidance. Agreed. The Boost UserAllocator is easier to implement and to use. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost memory management guidelines
On Friday, Aug 29, 2003, at 18:16 America/Denver, E. Gladyshev wrote: I'd like to start a new thread with Gregory's suggestion and my comments. Gregory Colvin wrote: ... * use the standard mechanisms (::operator new or std::allocator) when it is necessary Boost already has boost::allocator. IMO other boost libaries should consider using boost::allocator instead of ::new and std::allocator. There is a tradeoff between possibly better performance and possibly unwanted dependancies. ... * parameterize only when there is a clear advantage to doing so I'd modify it to * Consider parametrization if your library is to be available for embedded or non-traditional platfroms. Even on "traditional" platforms there may reason to parameterize, and there may be alternatives to parameterization even on embedded plaforms. * use the standard parameterization mechanisms (Allocator) when choosing to parameterize I'd add to it * Follow boost::allocator specification for allocator parameters Which specification is that? There are several here: http://boost.org/libs/pool/doc/interfaces.html ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost memory management guidelines
On Friday, Aug 29, 2003, at 18:05 America/Denver, David Abrahams wrote: Gregory Colvin <[EMAIL PROTECTED]> writes: * use the standard parameterization mechanisms (Allocator) when choosing to parameterize I'm not sure about this one. std::allocator are a mess, and almost everyone knows it. They were designed for containers, and they only barely work there, IMO. IMO they work just fine, and are not so messy as "everyone" thinks. The only real ugliness is rebind, but without template typedefs there isn't much choice. And the only really missing functionality is reallocation, but one can usually do without that. They can be difficult to implement well, but I think that is separate issue. Remember the weasel-wording about unequal allocators and the assumptions implementations are allowed to make about allocator's nested types? Remember it? I helped write it. It's unfortunate, as I explained earlier in this thread, but clear enough. It mainly serves to give implementors more latitude in how they implement their containers, and thus to give users fewer guarantees that fancy allocators will work. I really don't want to be in the position of forcing library authors to match users' expectations about the way their particular implementation's allocators work. No force here. If you choose to take any kind of template parameters you should be clear what you require of them, and where the standard provides a useable set of requirements it makes sense to point to them. But if you need something different then by all means specify what you need. And I wasn't aware that there was that much variation in std::allocator functionality, though I know there is some variation in whether the standard containers support stateful allocators and proxy pointers. From my point of view, by choosing the standard Allocator interface you get: * a standard set of requirements, with a few levels of strictness to choose from * a usually high-quality standard implementation (std:allocator) * a high quality Boost implementation (boost::pool_allocator) * the ability to play nicely with the standard containers In short, I think standard allocators are a squeaky wheel, but in most cases it better to grease that wheel than reinvent it. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 15:14 America/Denver, E. Gladyshev wrote: ... People are adopted to follow similar requirements for STL allocators anyway. I guess they can be recommended to all boost authors who wants to make memory management data types. Perhaps they can be added to the "Guidlines" section http://www.boost.org/more/lib_guide.htm#Guidelines At the least, we could add the following bullet * Discussion of memory management strategy. to http://www.boost.org/more/lib_guide.htm#Documentation I'm reluctant to say very much more at this point, as my opinions may not be suited to the needs of the many different libraries in Boost. But I think it's generally reasonable to: * not allocate memory unless it's really necessary * use the standard mechanisms (::operator new or std::allocator) when it is necessary * use custom allocation mechanisms only when there is a clear advantage to doing so * parameterize only when there is a clear advantage to doing so * use the standard parameterization mechanisms (Allocator) when choosing to parameterize * use custom parameterization mechanisms only when there is a clear advantage to doing so * document whether and how a library allocates memory ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 13:57 America/Denver, Gregory Colvin wrote: On Friday, Aug 29, 2003, at 13:34 America/Denver, E. Gladyshev wrote: ... All I am trying to say is that shared_ptr doesn't specify any requirements on its Deleter parameter. Bullshit: Please excuse my rude language. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 13:34 America/Denver, E. Gladyshev wrote: ... All I am trying to say is that shared_ptr doesn't specify any requirements on its Deleter parameter. Bullshit: template shared_ptr(Y * p, D d); Requirements: p must be convertible to T *. D must be CopyConstructible. The copy constructor and destructor of D must not throw. The expression d(p) must be well-formed, must not invoke undefined behavior, and must not throw exceptions. Effects: Constructs a shared_ptr that owns the pointer p and the deleter d. Postconditions: use_count() == 1 && get() == p . Throws: std::bad_alloc or an implementation-defined exception when a resource other than memory could not be obtained. Exception safety: If an exception is thrown, d(p) is called. Notes: When the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p as an argument. http://www.boost.org/libs/smart_ptr/shared_ptr.htm#constructors ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 12:33 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: [...] It's still not obvious to me. But I suspect I have yet to understand your example. Perhaps Peter can help me here. In his sample solution before, in this thread, he addresses this problem nicely by using static functions that take references to allocator instances. In his solution, shared_ptr doesn't create an internal Allocator copy. The C++ standard requires that a copy of an allocator is equivalent to the original. Instead he binds a static function pointer to an Allocator instance and uses the pointer as Deleter. My sample stateful allocator will work just fine in Peter's code. Right. If your allocators can't be copied safely then you have a problem. Peter's approach is one way to fix the problem. But I don't see that shared_ptr has a problem. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 10:48 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: [...] Does it make sense? Not to me. Sounds like a very broken allocator design. If I assume that I going to have a full control over my allocator instances (not a very unusual assumption), there is nothing broken here. Whether it is broken or not should be discussed in a specific context. Anyway, my point was that the shared_ptr( Data* p, Deleter ) has a *potential* problem that was not obvious even to to some people here. (it may not be obivous to other developers). It's still not obvious to me. But I suspect I have yet to understand your example. Like I said, I don't think that it is a big deal as soon as we state a set of requirements for boost "deleters"/allocators. (STL standard has). The "Common Requirements" section in the shared_ptr description doesn't seem to have them. The whole point of a shared_ptr is to invoke its deleter when the last shared_ptr to an object goes away. If intervening allocations cause the deleter to be invalid then either the deleter is broken or the code that did the allocations is broken. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Friday, Aug 29, 2003, at 00:52 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: On Thursday, Aug 28, 2003, at 23:48 America/Denver, E. Gladyshev wrote: *pseudo-code* template< typename T > sturct my_allocator { my_heap_control _heap; T* create() { return _heap.create(); } void operator()( T* d ) { _heap.destroy(d); } }; Now if I do something like the following code (that looks perfecly fine). f() { my_allocator a; { shared_ptr s( a.create(), a ); ... int* n = a.create(); a(n); } } I got a problem, because by the time when 's' deletes my data the heap state is changed while 's' still has an old copy of the heap state. * If we state that boost allocators must be implemented like statless policies not like real data types, this problem is not a big deal. I am not understanding the above at all, maybe because I don't know what you mean by "heap control block" or "stateless policies" or "real data types". I called "stateless policies" data types that define some actions (policies) that never change the state of any of this data type instances. The "heap control block" is a data type that manages the state of a memory heap. For instance it can keep a list/directory of pointers to free block in the heap. No imagine the the my_allocator has a list of pointers to free memory blocks in some memory heap. template< typename T > sturct my_allocator { char** _freeblocks[100]; }; When you write shared_ptr s( a.create(), a ); 's' will create an internal copy of 'a'. The internal copy will have a copy of _freeblocks[100]; Now we create a new object, that changes the state of _freeblocks[100] int* n = a.create(); Next, 's' goes out scope and deallocates its object using its own copy of _freeblocks[100] but this copy is already bad. It doesn't represent the current configuration of free blocks in the heap. Does it make sense? Not to me. Sounds like a very broken allocator design. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Thursday, Aug 28, 2003, at 23:48 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: [...] In this solution, there are some issues with who controls the instances of the allocator that allocates Data and instances that delete the Data. Which issues concern you? The potential problem is this. Let's assume that I forgot (or didn't know) that shared_ptr creates a copy of Deleter. I can technically create a local allocator class that will keep the heap control block as a data memeber. *pseudo-code* template< typename T > sturct my_allocator { my_heap_control _heap; T* create() { return _heap.create(); } void operator()( T* d ) { _heap.destroy(d); } }; Now if I do something like the following code (that looks perfecly fine). f() { my_allocator a; { shared_ptr s( a.create(), a ); ... int* n = a.create(); a(n); } } I got a problem, because by the time when 's' deletes my data the heap state is changed while 's' still has an old copy of the heap state. * If we state that boost allocators must be implemented like statless policies not like real data types, this problem is not a big deal. I am not understanding the above at all, maybe because I don't know what you mean by "heap control block" or "stateless policies" or "real data types". But I guess it is not big deal as soon as people understand it. If are to use template template parameters, Yes, the template template parameter is a pain. Probably better to take an arbitrary allocator object and rebind it: template shared_ptr(T* p, D d, const A& a) : px(p), pn(p, d, A::rebind< (a)) { detail::sp_enable_shared_from_this(p, p, pn); } it would be nice to be able to define one allocator type for both counter and data. template class Allocator> shared_ptr( Data*, Allocator, const Allocator >& ); This constructor would conflict with the constructors that take a deleter, which must be a function pointer or function object, and which might not use an allocator. Right, a new constructor is not needed. But for the purpose of creating shared objects using an allocator you could instead use a factory function something like: template shared_ptr allocate_shared_data(const Data& data, Allocator allocator) { struct deleter { Allocator a; deleter(const Allocator& a) : a(a) {} void operator()(Data* p) { a.deallocate(p,1); a.destroy(p); } }; Data* p = allocator.allocate(1); allocator.construct(p,data); return shared_ptr(p,deleter(allocator),allocator); } I like it. Or you can add operator()(Data*) to your allocator and use it directly in shared_ptr and STL. Right. template< typename T > struct my_allocator : std::alocator { void operator()(T* d) { try { d->~T(); } catch(...) { deallocate(d, 1); throw std::runtime_error(""); } deallocate(d, 1); return; } }; shared_ptr s( p, my_allocator(), my_allocator() ); I am not sure how to specify the counter allocator in this case What is legal syntax for template template parameters in functions? We just got rid of the template template parameter. Do you have to put the whole thing in. shared_ptr s( p, my_allocator(), my_allocator >() ); or there is another way? my_allocator a; shared_ptr s(p,a,a); ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Thursday, Aug 28, 2003, at 19:40 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: shared_ptr doesn't allocate the data, it only deletes it, which is the job of the current deleter parameter. And the counter type is by design not part of the shared_ptr type, so it doesn't belong as parameter to the shared_ptr template. See: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/boost/boost/boost/ shared_ptr.hpp So you what you might want is to add something more like this to shared_ptr: template class Allocator> shared_ptr( Data*, Deleter, const Allocator >& ); The idea being that you can use this constructor to get complete control over how a particular shared_ptr manages memory. In this solution, there are some issues with who controls the instances of the allocator that allocates Data and instances that delete the Data. Which issues concern you? But I guess it is not big deal as soon as people understand it. If are to use template template parameters, Yes, the template template parameter is a pain. Probably better to take an arbitrary allocator object and rebind it: template shared_ptr(T* p, D d, const A& a) : px(p), pn(p, d, A::rebind< >(a)) { detail::sp_enable_shared_from_this(p, p, pn); } it would be nice to be able to define one allocator type for both counter and data. template class Allocator> shared_ptr( Data*, Allocator, const Allocator >& ); This constructor would conflict with the constructors that take a deleter, which must be a function pointer or function object, and which might not use an allocator. But for the purpose of creating shared objects using an allocator you could instead use a factory function something like: template shared_ptr allocate_shared_data(const Data& data, Allocator allocator) { struct deleter { Allocator a; deleter(const Allocator& a) : a(a) {} void operator()(Data* p) { a.deallocate(p,1); a.destroy(p); } }; Data* p = allocator.allocate(1); allocator.construct(p,data); return shared_ptr(p,deleter(allocator),allocator); } ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Thursday, Aug 28, 2003, at 16:26 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: How will I even know it, the documentation is completely ignorant on the memory issues. Perhaps because you work with the authors of the documentation to make it sure it says what needs saying? Are the documentation authors monitoring this mailing list? And I have no objection myself to adding an allocator parameter to the shared_ptr constructor, or to making some other change that serves the purpose. So if you need a change, why not just do it, try it out, and submit a patch? How about template< typename T, typename Counter = int > shared_ptr { typedef Counter counter; //counter type should be public template , typename CounterAlloc=std::allocator shared_ptr( const DataAlloc& da = DataAlloc(), const IntAlloc ia& = CountAlloc() ); }; shared_ptr doesn't allocate the data, it only deletes it, which is the job of the current deleter parameter. And the counter type is by design not part of the shared_ptr type, so it doesn't belong as parameter to the shared_ptr template. See: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/boost/boost/boost/ shared_ptr.hpp So you what you might want is to add something more like this to shared_ptr: template class Allocator> shared_ptr( Data*, Deleter, const Allocator >& ); The idea being that you can use this constructor to get complete control over how a particular shared_ptr manages memory. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Thursday, Aug 28, 2003, at 16:54 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: And I have no objection myself to adding an allocator parameter to the shared_ptr constructor, or to making some other change that serves the purpose. So if you need a change, why not just do it, try it out, and submit a patch? Just wondering what is the submission procedure exactly? Dunno. My last submission was too long ago. For example I believe that shared_ptr must absolutely have the counter type as a template parameter. And I believe it absolutely must not: http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: what happened to allocators in boost?
On Thursday, Aug 28, 2003, at 10:46 America/Denver, E. Gladyshev wrote: --- Peter Dimov <[EMAIL PROTECTED]> wrote: You can use all smart pointers except shared_ptr and shared_array as they do not allocate any memory. In particular, intrusive_ptr is a good candidate if memory is a concern as it has smaller memory footprint than shared_ptr. Thanks, I'll consider it next time. However if Boost doesn't have a clear memory management concept, how can I guarantee that the next time around, intrusive_ptr or something else in boost won't start allocating memory under the covers. It is perfectly legal in Boost. Of course future releases of Boost are free to change in completely arbitrary ways that break anything we want. The same is true of the C++ standard, operating system APIs, CPUs, and everything else. So there are no guarantees that you can release a library today and have it keep working with all future releases of Boost, C++, etc. Nonetheless, backwards compatibility matters, and Boost is no more likely to change in ways that break your code than anything else. And to the extent you remain active in Boost, you can help see to it that such changes don't happen. How will I even know it, the documentation is completely ignorant on the memory issues. Perhaps because you work with the authors of the documentation to make it sure it says what needs saying? You can also use Boost.Regex, it is completely allocator-enabled. ;-) I never said that I am a huge allocators fan but at least it seems that regex has one of the most consistent memory management concepts in the library. :) And I have no objection myself to adding an allocator parameter to the shared_ptr constructor, or to making some other change that serves the purpose. So if you need a change, why not just do it, try it out, and submit a patch? I also have no objection, and much sympathy, for having a clear memory management policy for Boost libraries. But again, it is a matter of people who care about and understand the issue doing the necessary work, just like everything else here at Boost. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Re: what happened to allocators in boost?
On Tuesday, Aug 26, 2003, at 10:41 America/Denver, E. Gladyshev wrote: --- Gregory Colvin <[EMAIL PROTECTED]> wrote: For shared_ptr the count is allocated by the following line in the shared_count constructor: new sp_counted_base_impl(p, d); So it might be possible to make the allocation customizable by specializing sp_counted_base_impl. I think it would be great. Then I suggest giving it a try. However there is another problem. You have to new your object. shared_ptr s( new MyClass ); You cannot use allocator like you would expect: shared_ptr< MyClass, std::allocator > s; Right. The shared_ptr design carefully avoids any extra class template parameters, in favor of parameterizing the constructor. My idea, if it works, would be to specialize sp_counted_base_impl on the pointer type P, e.g. MyClass*, so you just write shared_ptr s( new MyClass ); or on the deleter type D, so you would write, e.g. shared_ptr s( new MyClass, MyDeleter> ); The idea is that your sp_counted_base_impl specialization provides a custom operator new and operator delete that uses your allocator. Alternatively, we could consider adding shared_ptr constructor that takes an allocator argument. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Re: what happened to allocators in boost?
For shared_ptr the count is allocated by the following line in the shared_count constructor: new sp_counted_base_impl(p, d); So it might be possible to make the allocation customizable by specializing sp_counted_base_impl. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: converting Boost to other programming languages
On Monday, Aug 25, 2003, at 11:46 America/Denver, David Abrahams wrote: Daniel Frey <[EMAIL PROTECTED]> writes: Mohamed Iqbal wrote: For now I will cnvert three or four libraries for academia purposes but a bigger number of libraries will be ported to my new language when the commercial release is ready. I think it would be best if you convert the three or four libraries you have in mind, prepare it the way you like to redistribute/sell it and show the result to us *before* redistribution. It's easier to say: "This is OK" or "This is not OK" when we have something to look at instead of giving you a Carte Blanche. I'm afraid the license already gives him Carte Blanche. Why be afraid? The license is intended to give Carte Blanche. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] GUI/GDI template library
On Wednesday, Aug 6, 2003, at 17:36 America/Denver, Brock Peabody wrote: From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Gregory Colvin Sent: Wednesday, August 06, 2003 4:48 PM To: Boost mailing list Subject: Re: [boost] GUI/GDI template library Why the S? On Wednesday, Aug 6, 2003, at 16:37 America/Denver, E. Gladyshev wrote: --- Brock Peabody <[EMAIL PROTECTED]> wrote: That sounds good. What if we called the lower layer boost::gui and the upper layer boost::sgtl? It stands for 'standard'. Maybe that's a little pretentious for us at this early stage :) Yes, far too pretentious. IMHO. gtl would probably be better. I suspect that if we get to a review some people may request something more verbose. Brock ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] GUI/GDI template library
Perhaps Perseus, who slew the Medusa, the snake-haired monster of "so frightful an aspect that no living thing could behold her without being turned into stone." Perseus avoid being turned to stone by clever use of indirection -- he avoided looking directly at Medusa, instead looking only at her reflection in the mirror of his polished shield. http://www.online-mythology.com/perseus_medusa/ On Thursday, Aug 7, 2003, at 11:52 America/Denver, Brock Peabody wrote: On Behalf Of E. Gladyshev [...] Don't know where to start... Greek and Roman mythology? 'Aquilo' the north wind, the ruler of the winds. 'Notus' the south wind 'Flora' goddess of flowers and spring. 'Arcadia' a district of the Peloponnesus, the home of pastoral simplicity. Hmm of those I like Notus. Other ideas: Atlas Hydra Muse ... Eugene, you brought this whole thread up so I think you should pick the name :) ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] GUI/GDI template library
Why the S? On Wednesday, Aug 6, 2003, at 16:37 America/Denver, E. Gladyshev wrote: --- Brock Peabody <[EMAIL PROTECTED]> wrote: That sounds good. What if we called the lower layer boost::gui and the upper layer boost::sgtl? Agreed. __ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: GUI/GDI template library
Been there, done that, twice, and don't care to do it again ;-> On Wednesday, Jul 30, 2003, at 13:53 America/Denver, David Abrahams wrote: Has anyone given thought to the design of a domain-specific sublanguage for dialog layout specification? -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: GUI/GDI template library
On Tuesday, Jul 29, 2003, at 16:02 America/Denver, Brock Peabody wrote: On Behalf Of Gregory Colvin [...] For this kind of localization loading the localized resources at runtime is essential. Regenerating C++ code and rebuilding the application is not an option. Why would it be necessary to reload anything besides the localized text? That wouldn't be too hard: gui_application app = row(localized_text(name_text_id), edit(&employee::name)); Are you going to change the behavior of the application from one country to another? Yes, you might. But I think text and graphics are most often changed, and in the case I am describing this must be done with native resources. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: GUI/GDI template library
On Tuesday, Jul 29, 2003, at 16:24 America/Denver, Bohdan wrote: "Brock Peabody" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] On Tuesday, Jul 29, 2003, at 12:25 America/Denver, Brock Peabody wrote: ... I don't think custom resource files would be any easier to edit that inline C++ code. I think they would be much less easy to edit and read. It's been a few years, but the last time I was writing a GUI application for an international market the shops in Japan, Korea, and Ireland that we paid to localize the application required platform-native resource files as their starting point. Neither custom resources nor C++ code would have been acceptable. And before that, when I was at XVT, we put a lot of work into supporting native resource files in our portable GUI toolkit. It might not be too hard to make the GUI objects 'serialize' themselves into a native resource file but this would be useless without something to convert a resource file back into C++ code. Something like this could be written on top of a pure C++ solution with the help of a serialization library. Sure, but this can be kind of simple c++ or even c code. Alternatively very important is possibility to load resources in runtime, possibly this can help to solve localization issues. For this kind of localization loading the localized resources at runtime is essential. Regenerating C++ code and rebuilding the application is not an option. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: GUI/GDI template library
On Tuesday, Jul 29, 2003, at 12:25 America/Denver, Brock Peabody wrote: ... I don't think custom resource files would be any easier to edit that inline C++ code. I think they would be much less easy to edit and read. It's been a few years, but the last time I was writing a GUI application for an international market the shops in Japan, Korea, and Ireland that we paid to localize the application required platform-native resource files as their starting point. Neither custom resources nor C++ code would have been acceptable. And before that, when I was at XVT, we put a lot of work into supporting native resource files in our portable GUI toolkit. ___ 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
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: Re: Proposed smart_handle library
On Saturday, Jul 19, 2003, at 20:52 America/Denver, Ross Smith wrote: On Sunday 20 July 2003 11:46, Gregory Colvin wrote: On Saturday, Jul 19, 2003, at 17:16 America/Denver, Ross Smith wrote: ... (Of course all of these could easily be unified into a single policy-based type; unfortunately the Powers That Be seem to have decided that policies are too complicated for us mere mortals to be trusted with.) 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. There have been many postings and much discussion pro and con policy- based smart pointers, but no formal proposal. Only if such a proposal were turned down would it be fair to say that Boost as such had made any decision, let alone to speculate on the motivation for such a decision. My bet is that such a proposal would succeed, but would have to be of very high quality to meet Boost's critical standards and do justice to the inherent difficulty of the problem space. I hope that someday soon someone will volunteer such a proposal, but in the meantime, I think John's handles are a very good idea. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Proposed smart_handle library
On Saturday, Jul 19, 2003, at 17:16 America/Denver, Ross Smith wrote: ... (Of course all of these could easily be unified into a single policy-based type; unfortunately the Powers That Be seem to have decided that policies are too complicated for us mere mortals to be trusted with.) There are no Powers That Be. Boost has no policy-based smart pointers because nobody has done the difficult job of proposing them. ___ 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] Draft of new Boost Software License
On Wednesday, Jul 2, 2003, at 02:42 America/Denver, Paul A. Bristow wrote: | In non-Boost code, I've seen wording something like "See the attached | license; if it is missing see www.foo.org/license." Maybe something like | that is what will be recommended. | | They've already signed off on the concept of a single copy of the license. | It is just the exact way to refer to it that hasn't been finalized. | | --Beman May I suggest consideration of what happens in a decade or two when boost.org might not longer exist to provide a reference, but we still need to ensure that the license terms are still available. Would it be best to refer (additionally perhaps) to a Digital Object Identifier (see doi.org) which provides a permanent reference to the actual license file. So if boost.org is renamed, say, the reference is still correct because it will be 'resolved' (in the DOI jargon) to a new location as boostTwo.org. This seems like a lot more trouble than just pasting our brief license into every source file. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] why no strict ownership smart pointer in boost
On Tuesday, Jul 1, 2003, at 17:36 America/Denver, Schoenborn, Oliver wrote: On Tuesday, Jul 1, 2003, at 14:38 America/Denver, Boost wrote: I did a search in the archives and found nothing on this: Why is there no strict-ownership smart-pointer in boost? Just curious to know what the reasons are. Thanks, What do want beyond what boost::scoped_ptr and std::auto_ptr provide? Ability to be used in STL containers, and explicit transfer of ownership capabilities (e.g. *no* move-on-copy etc). So what would the copy semantics be? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] why no strict ownership smart pointer in boost
On Tuesday, Jul 1, 2003, at 14:38 America/Denver, Boost wrote: I did a search in the archives and found nothing on this: Why is there no strict-ownership smart-pointer in boost? Just curious to know what the reasons are. Thanks, What do want beyond what boost::scoped_ptr and std::auto_ptr provide? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Draft of new Boost Software License
On Thursday, Jun 26, 2003, at 07:53 America/Denver, William E. Kempf wrote: ... But it would be nice to just refer to the license instead of repeating it in every single file. Though this license is brief enough that inclusion is no big deal. It seems that doing it by reference to a web page amounts to Boost reserving the right to change terms in the future, possibly to the disadvantage of the authors and users. But I see lots of code that refers to the GPL that way, so this is another question for the lawyers. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] shared_cyclic_ptr question
On Wednesday, Jun 4, 2003, at 08:22 America/Denver, Philippe A. Bouchard wrote: Greetings Boost, I am not that much familiar with garbage collection techniques so please excuse me if the technique I am thinking of is already used somewhere. Let's say: - you can easily detect weither an object was allocated on the stack or on the heap; - a smart pointer contained within an object can somehow access it's "object header" when the object was allocated on the heap with a placement operator new(); Neither of which can be done portably. Given: Node = element of a possible cyclic graph allocated on the heap. Entity = possible cyclic graph in its entirety allocated on the heap. struct entity_header { int count; }; struct node_header { int count; entity_header * p_entity; }; // Erroneous but simple allocation example: inline void * operator new (size_t s, gc const &) { return malloc(s + sizeof(node_header)) + sizeof(node_header); } template struct smart_pointer { template smart_pointer(U * p) : m_p(p) { if (is_on_the_stack(this)) { // Allocate an entity_header and affect its address to m_p's header->p_entity. * // Initialize m_p's header->p_entity->count to 1. } // 'this' is part of a node with a header on the heap. else { // Copy the this's header->p_entity to m_p's header->p_entity. ** } ... } template smart_pointer(smart_pointer const & p) : m_p(p.m_p) { // Possible merge / fragmentation of two entities. *** ... // Possible incrementation / decrementation of this's header->p_entity->count and m_p's header->p_entity->count. } ~smart_pointer() { if (m_p && m_p's header->p_entity->count == 1) { // Force an entity's destruction. * } } ... private: T * m_p; }; Then: An entity_header will be allocated each time a pointer on the stack refers to a new node on the heap (*) and every other node derived from this root node will refer to the same entity_header with node_header::p_entity. If a new pointer on the stack refers to the entity, its entity_header::count will be incremented. If the last pointer on the stack refers to the entity then the entire entity will be destructed (no more possible cyclic graph). Ex.: template struct rope; // cyclic entity smart_pointer< rope > p = new (gc) rope(10);// entity_header::count == 1 smart_pointer< rope > q = p;// entity_header::count == 2 p.~smart_pointer< rope >();// entity_header::count == 1 q.~smart_pointer< rope >();// entity_header::count == 0, destruction Thus: The purpose of the entity_header is to know the number of times the entity is refered by a pointer on the stack. Do this algorithm already has a name? If so, why aren't you using it since there is no need to scan the graph looking up for dangling entities. It may take a little bit more memory (1 more pointer per node + 1 entity_header per heap graph) but I think the cost / benefits here are quite acceptable since the speed will always be O(1). Regards, Philippe ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: an XML API in boost
It's worth noting that libxml2 is itself open source with what appears to be Boost compatible license: http://www.opensource.org/licenses/mit-license.html On Tuesday, Jun 3, 2003, at 20:21 America/Denver, Darryl Green wrote: From: William E. Kempf [mailto:[EMAIL PROTECTED] Vladimir Prus said: William E. Kempf wrote: If a submitted library required libxml2, I'd personally vote no. If the interface was supposed to be portable to other backends, I'd probably still vote no unless at least one other backend was included as proof of concept. It would still be nice to have a Boost supplied backend, probably via Spirit, but so long as I was confident that I was not tied to any specific non-Boost library, it wouldn't matter that much. I tend to disagree here. Writing XML library is not easy, and libraries like expat and libxml2 are already here, working and debugged. ... Careful with what you disagree with. I stated that it would still be nice to have a Boost supplied backend, but I didn't state this was a requirement. What I think *is* a requirement is that any wrapper library not be tied to a single backend, and I personally believe that what follows from that is that the submission must have at least 2 referenced backends for proof of concept. Note that this is precisely what Boost.Threads does, for instance. I agree that the interface shouldn't be too tightly bound to the underlying library. imho the interface Stefan has written isn't tightly coupled to libxml2 in the sense that the interface would need to change or be a poor fit on some other library. However, the implementation (and efficiency) of the wrapper is certainly aided by the libxml2 library interface needing only a very thin c++ veneer, and libxml2 being very comprehensive in its facilities. As a user, I had already decided to use libxml2 and wrap it when Stefan posted. The decision was based on code size, performance and features of the xml lib. I had already looked at using Spirit, and found the example xml parser too slow in comparison to other parsers, in particular expat and libxml2. To provide the same facilities as libxml2 requires considerably more than just a parser - performance issues aside. I can't think of a good reason for wanting to apply stephen's interface to another underlying xml lib, until or unless there is a better performing xml lib than libxml2. I would suggest that the portability (or otherwise) of Stefan's library could be assessed/reviewed without necessarily requiring another implementation for which there would likely be no users. This is a bit different to threads, (warning: Alexander bait) where there is clearly a requirement to use the native platform library facilites, and these facilities differ significantly. There isn't really that much variation in how one presents xml using a dom, sax and xpath based interface - it just needs a c++ "language binding". Regards Darryl Green. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Cyclic pointers - a comparison of known Boost efforts
On Friday, May 30, 2003, at 12:38 America/Denver, Chuck Messenger wrote: Gregory Colvin wrote: Thanks, but your description of cyclic_ptr is pretty far off the mark. Sorry -- hopefully you'll forgive my ignorance. I'm just throwing out what I understand to be the case, in the hopes that someone (such as yourself) would set me straight... It does not maintain a global map, and copying cyclic_ptr cost the same as copying shared_ptr. OK, I'll have to review the old messages again. I thought someone had said cyclic_ptr used a global map. Sorry. I suppose better yet would be for me to study your actual *code*... Larry's analysis gives a better explanation than I could. Do you do a raw scan of memory, like sp_collector, then? (i.e. not perfect discovery) No. The self-assignment trick is precise, unless it is foiled by a user-written operator=. The special assignment mode is used only during the mark phase of a collection, and costs more or less the same as any other discovery method. Suppose I have the structure: struct Image { char huge_image[ONE_ZILLION]; cyclic_ptr ptr; }; As I understand it, in order to discover 'ptr', you'd invoke operator=() on each Image structure you came to. Correct, or incorrect? Correct. So it would be smart to write an operator= for Image that avoids copying huge_image to itself. And it would best if the uber-pointer used a less intrusive discovery method. I think sp_collector is on the right track, if it could be made precise. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)
On Friday, May 30, 2003, at 11:58 America/Denver, Larry Evans wrote: Gregory Colvin wrote: > On Friday, May 30, 2003, at 10:18 America/Denver, Larry Evans wrote: > [snip] >> >> http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/ >> draft-compare.zip might be a good starting point. It >> doesn't include the latest additions and still needs work :(. > > > Wow. Thanks (I guess). Since understanding some of the code was difficult, I think you understood cyclic_ptr better than I do now, and maybe better than I did then ;-> it would sure help if the authors of each of the codes would analyze their own code to check against what's already in draft-compare, or add to draft-compare, as appropriate. Also, it would most likely avoid the "jumping to conclusions" which I was guilty of when evaluating sp_collector earlier in a (this?) thread. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Cyclic pointers - a comparison of known Boost efforts
Thanks, but your description of cyclic_ptr is pretty far off the mark. It does not maintain a global map, and copying cyclic_ptr cost the same as copying shared_ptr. The special assignment mode is used only during the mark phase of a collection, and costs more or less the same as any other discovery method. On Friday, May 30, 2003, at 11:56 America/Denver, Chuck Messenger wrote: Gregory Colvin wrote: On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger wrote: ... What I'm trying to develop (or even better, find) is a workable C++ library which supports cyclic structures, handling garbage collection for you, without resorting to a systemic (and non-portable) approach like the Boehm collector. I want to build regular-old, C++ standard libraries upon this cyclic library -- I don't want to require users of my libraries to use my garbage collection system. It needs to be perfectly invisible to the user (and ideally, as invisible as possible to the library writer). There are a few attempts laying around various places in Boost, but I've lost track of where they all are, how they all work, and what their relative advantages and disadvantages are. If someone could pull this information together it might help to get this discussion out of the cycle it seems caught in ;-> Let's do it! I've been working (slowly!) toward just that. Very briefly, here's what I've found so far -- please tear it apart at will: 1. Systemic approaches like the Boehm collector (no Boost libs). These aren't, and can't be, anything close to Standard C++, so they're out of the realm of what I think we on Boost are interested in (for inclusion in a Boost library, that is -- we're still interested in them...) 2. sp_collector - by Peter Dimov. In Boost distro -- see boost/libs/smart_ptr/src/sp_collector.cpp. This is an experimental extension to shared_ptr. It makes the assumption that all shared_ptr's are contained within objects owned by other shared_ptr's. It uses the "Boehm-like" trick of scanning raw memory to find the shared_ptr's (I believe this is called "conservative collection"), so it isn't 100.000% foolproof (but is close). More importantly, it doesn't work with the STL containers, which makes it nothing more than an experimental toy (but an interesting one). 3. cyclic_ptr - by Greg Colvin (i.e. yours). See http://groups.yahoo.com/group/boost/files/smart_pointers/cyclic_ptr. I haven't studied it yet, but based on what I've read in recent threads, I believe it works by tracking the locations of all cyclic_ptr objects, in a global map. This means it *is* 100.000% foolproof (unlike sp_collector). However, it also means there is a severe overhead to copying cyclic_ptr's. In order to "discover" the object dependency graph of an object, it makes a copy of it. During the copy operation, cyclic_ptr's are put in a special mode, so that during their operator=(), they tally the dependency graph. One problem with this is that each object must then be copyable. This can be messy if you're making extensive use of non-copyable objects, such as in the Boost Threads library. Also, it can lead to unbounded inefficiency in the case of objects with lots of non-cyclic-ptr material, which is intended to be copyable (for example, imagine an image class). 4. shared_cyclic_ptr - by Larry Evans. See http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr. This one seems to be under active development right (new version uploaded a day or two ago). Again, I haven't studied this one yet. About the "discovery" problem, Larry writes: "[it] works around this by using a smart ptr enumerator function specialized for each type of container". As I understand this, it means that shared_cyclic_ptr objects must either be within objects owned by another shared_cyclic_ptr (as with sp_collector), or they can be in "tagged" STL containers, e.g.: template struct SpecialList : public list, public SpecialTag { }; That would be a best case. Or, it might be necessary to do something much messier, like this: template struct SpecialList { // Implement wrapper for each std::list function... private: list list_; }; Perhaps Larry can comment. 5. juju_ptr -- my own effort, under development. Perhaps if I finish it, I'll upload it for public examination. If you're even luckier, I may change the name. I'm using a unique (I think) discovery method -- some "wicked juju" (but, I believe, adhering to Standard C++, and portable) -- which avoids cyclic_ptr
Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)
On Friday, May 30, 2003, at 10:18 America/Denver, Larry Evans wrote: Gregory Colvin wrote: On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger wrote: ... What I'm trying to develop (or even better, find) is a workable C++ [snip] their relative advantages and disadvantages are. If someone could pull this information together it might help to get this discussion out of the cycle it seems caught in ;-> http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/ draft-compare.zip might be a good starting point. It doesn't include the latest additions and still needs work :(. Wow. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)
On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger wrote: ... What I'm trying to develop (or even better, find) is a workable C++ library which supports cyclic structures, handling garbage collection for you, without resorting to a systemic (and non-portable) approach like the Boehm collector. I want to build regular-old, C++ standard libraries upon this cyclic library -- I don't want to require users of my libraries to use my garbage collection system. It needs to be perfectly invisible to the user (and ideally, as invisible as possible to the library writer). There are a few attempts laying around various places in Boost, but I've lost track of where they all are, how they all work, and what their relative advantages and disadvantages are. If someone could pull this information together it might help to get this discussion out of the cycle it seems caught in ;-> ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
On Thursday, May 29, 2003, at 21:25 America/Denver, Larry Evans wrote: Gregory Colvin wrote: [snip] Do you really need a precise collector? Boehm's collector works just fine. Most people don't, but some do. In Jones and Lins _Garbage Collection_ there's mention of "misidentification" or "false" pointers in applications with large compress bitmaps. Also, for highly connected structures, I remember reading that there could be a problem. So don't allocate bitmaps and such with GC_malloc. Other than that the problem seems to be mostly theoretical. If so, I don't think you can do it without compiler support. I was hoping stl_container.cpp would be as close as possible w/o compiler support. Not close enough for me. I think Detlef also mentioned this somewhere in his article. The closer it is, then the less testing would need to be done to change the compiler. Well, if standard allocators supported proxied pointers you could do it with a collected allocator. I think Dinkum's allocators do, not sure about other standard libraries. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
On Thursday, May 29, 2003, at 20:52 America/Denver, Larry Evans wrote: Gregory Colvin wrote: Check out http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html [snip] On Thursday, May 29, 2003, at 19:57 America/Denver, Larry Evans wrote: Gregory Colvin wrote: [snip] > It is not that hard to write a new(gc) and gc_allocator > using Boehm's collector, for those who don't want to have > the collector take over all memory allocation. I found John Max Skaller's posts on such a gc_allocator: http://aspn.activestate.com/ASPN/Mail/Message/boost/1150154 Since I still can't figure out how he did it, maybe he could provide code or more details on howto. However, I don't know his email. I may just download his Felix compiler and try deciphering the code. Now, how do we do something similar with a precise gc like that proposed earlier? Do you really need a precise collector? Boehm's collector works just fine. If so, I don't think you can do it without compiler support. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
Also check out http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt for a gc base clase to inherit from. On Thursday, May 29, 2003, at 20:20 America/Denver, Gregory Colvin wrote: Check out http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html which provides a gc_alloc, and for new(gc) all you need is something like this: struct gc_t {}; static const gc_t gc; void* operator new (size_t n, const gc_t&) { return GC_malloc(n); } void* operator new[](size_t n, const gc_t&) { return GC_malloc(n); } void operator delete (void* ptr, const gc_t&) {} void operator delete[](void* ptr, const gc_t&) {} Much easier than hacking shared_ptr. On Thursday, May 29, 2003, at 19:57 America/Denver, Larry Evans wrote: Gregory Colvin wrote: [snip] > It is not that hard to write a new(gc) and gc_allocator > using Boehm's collector, for those who don't want to have > the collector take over all memory allocation. I found John Max Skaller's posts on such a gc_allocator: http://aspn.activestate.com/ASPN/Mail/Message/boost/1150154 Since I still can't figure out how he did it, maybe he could provide code or more details on howto. However, I don't know his email. I may just download his Felix compiler and try deciphering the code. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
Check out http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcinterface.html which provides a gc_alloc, and for new(gc) all you need is something like this: struct gc_t {}; static const gc_t gc; void* operator new (size_t n, const gc_t&) { return GC_malloc(n); } void* operator new[](size_t n, const gc_t&) { return GC_malloc(n); } void operator delete (void* ptr, const gc_t&) {} void operator delete[](void* ptr, const gc_t&) {} Much easier than hacking shared_ptr. On Thursday, May 29, 2003, at 19:57 America/Denver, Larry Evans wrote: Gregory Colvin wrote: [snip] > It is not that hard to write a new(gc) and gc_allocator > using Boehm's collector, for those who don't want to have > the collector take over all memory allocation. I found John Max Skaller's posts on such a gc_allocator: http://aspn.activestate.com/ASPN/Mail/Message/boost/1150154 Since I still can't figure out how he did it, maybe he could provide code or more details on howto. However, I don't know his email. I may just download his Felix compiler and try deciphering the code. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
On Thursday, May 29, 2003, at 09:57 America/Denver, Larry Evans wrote: Gregory Colvin wrote: [snip] It seems that rather than take the route of modifying all the standard containers one might as well just provide a special operator new(gc) and gc_allocator that can track all the memory blocks on the heap that might contain a shared_ptr. Then one can either replace global operator new with the special one, or use new(gc) or gc_allocator wherever needed. I'm assuming that the advantage of the suggested method over Boehm's collector would be the precision? I.e. no false pointers are possible? Yes, that would be one (small) advantage. It would also be easier to provide a portable version. The disadvantage is the need to use smart pointers at all. It is not that hard to write a new(gc) and gc_allocator using Boehm's collector, for those who don't want to have the collector take over all memory allocation. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] smart_ptr: sp_collector can't handle STL containers ofshared_ptr's
On Thursday, May 29, 2003, at 08:45 America/Denver, Chuck Messenger wrote: ... And so, sp_collector suffers the same problem as shared_cyclic_ptr, and requires the same remedy: that is, it is necessary to be able to "tag" a container as being one which might hold "internal" shared_ptr's. Any interest in modifying shared_ptr to support something like this? Yes, but I haven't had time since my cyclic_ptr work. It seems that rather than take the route of modifying all the standard containers one might as well just provide a special operator new(gc) and gc_allocator that can track all the memory blocks on the heap that might contain a shared_ptr. Then one can either replace global operator new with the special one, or use new(gc) or gc_allocator wherever needed. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)
On Wednesday, May 28, 2003, at 13:04 America/Denver, Chuck Messenger wrote: Larry Evans wrote: Chuck Messenger wrote: [snip] collections, put them in object heirarchies, etc). This freedom should ideally apply both internally (within library L code) and most importantly, externally (in the code of users of library L). Crucially, Would you require the users to use a smart pointer instead of a raw? If not, then you're only option, that I can tell, is use a conservative collector like Boehm's. No -- users don't use pointers -- only objects. The objects each have one pimpl_ (which will be whatever "smart" type "we" - the uber-pointer framework designers - want), pointing to the underlying object. Note: This is essentially a plain-vanilla Java-style object system which I am describing. The consequence of mis-identification is that you may fail to destroy some unused objects. If this leads to nothing worse than some leaked memory, then it's not a real problem -- it will be a vanishingly small amount of memory. This is the justification for Boehm's conservative collector. http://www.hpl.hp.com/personal/Hans_Boehm/gc/ Does the Boehm collector likewise do a full scan of the heap? I assume so... It marks all objects on the heap pointed to by the machine registers, and all objects pointed to by those objects, and so on. It is conservative in the sense that it cannot generally tell whether a register or memory cell contains a pointer or an integer. One big problem with this approach is that you end up having to scan all of your memory. This could (and for me, would) be an outrageous proposition, as only a tiny portion of memory relates to my object set. Most of it will be raw data (e.g. images, etc). Boehm's collector includes functions for allocating pointer-free memory. This is what Christopher's (alias= global rc mark-scan) algorithm does. It's also what mark-sweep algorithms do, i.e. they have to mark all reachable objects, and then scan thru the whole heap sweeping the unmarked into the garbage collector. However, since this global scan is done, usually, infrequently, the time isn't that big a factor, at least compared with the updating of reference counts during each pointer copy. That's why Boehm's gc should work faster than refcounting. It does. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: in/outparameters,codingstylesandmaintenance[was:classproposal]
Somewhere in this thread I lost track of this -- but just how do out<> and in<> differ from ref<> and cref<>? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Is a 3% timing difference reliably repeatable in realcode?
On Thursday, May 8, 2003, at 11:07 America/Denver, Beman Dawes wrote: At 11:11 AM 5/8/2003, Darin Adler wrote: >On Thursday, May 8, 2003, at 07:04 AM, Beman Dawes wrote: > >> A 2-3% timing difference probably isn't reliably repeatable in real >> code. >> >> How code and data happens to land in hardware caches can easily swamp >> out such a small difference. The version-to-version or step-to-step >> differences in CPU's, memory, compilers, or operating systems can >> cause that much difference in a given program. Differences need to get >> up into the 20-30% range before they are likely to be reliably >> repeatable across different systems. >> >> At least that's been my experience. > >That has not been my recent experience. While working on my current >project (the Safari web browser), we have routinely made 1% speedups >that are measurable and have an effect across multiple machines and >compilers (same basic CPU type and operating system), and we have also >detected 1% slowdowns when we inadvertently introduced them. I notice the examples you give are JavaScript. Greg's example of a virtual machine is written mostly in C, IIRC. I wonder if C++ is more sensitive to compiler differences? For example, some C++ compilers are a lot more aggressive about inlining than others. For some of the code I've timed, a change slowed results for a compiler that failed to inline it, but ran quicker for the compiler that was good at inlining. Makes sense. Boost code stresses compilers in ways that our code doesn't -- the need to be as portable as we are means we don't even use all the features of C89, let alone C++ or C99. And of course C89 doesn't have things like inlining and virtual function dispatch that can vary so much across C++ compilers. Plus we spend a fair amount of time inspecting the output of our compilers and tweaking our C code until we get what we want, and preserving the tweaks in platform-specific macros. The fact remains that it takes a lot of 3% tweaks to make a big difference, so until you know you have the best possible data structures and algorithms there isn't much point, and when there is a point it is painstaking work at the limits of measurability. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Is a 3% timing difference reliably repeatable in realcode?
My experience tuning our java VM is similar, and it runs on a lot of different CPUs. Still, there is reason to be suspicious of very small changes, which might be repeatable for our benchmark set, yet have no real meaning for normal use. And there is reason to be careful not to waste time pursuing 3% tweaks instead of going for 100% breakthroughs. On Thursday, May 8, 2003, at 09:11 America/Denver, Darin Adler wrote: On Thursday, May 8, 2003, at 07:04 AM, Beman Dawes wrote: A 2-3% timing difference probably isn't reliably repeatable in real code. How code and data happens to land in hardware caches can easily swamp out such a small difference. The version-to-version or step-to-step differences in CPU's, memory, compilers, or operating systems can cause that much difference in a given program. Differences need to get up into the 20-30% range before they are likely to be reliably repeatable across different systems. At least that's been my experience. That has not been my recent experience. While working on my current project (the Safari web browser), we have routinely made 1% speedups that are measurable and have an effect across multiple machines and compilers (same basic CPU type and operating system), and we have also detected 1% slowdowns when we inadvertently introduced them. They add up. Ten 1% speedups result in a 9.5% speedup. It's true that differences in CPUs, memory, compilers, and operating systems can cause huge differences, but that does not mean that changes that make such small increases in performance are therefore not worthwhile. In our project, a 3% speed increase is considered a cause for celebration. I'm not sure, though, if this negates your point, Beman. Something that gives a 2-3% speedup for one Boost user might not be worth any level of obfuscation unless we can prove it provides a similar speedup for other Boost uses. -- Darin PS: On the occasions where you can fix an algorithm in a way that gives a 10x speed increase, or a 25% one, that's even more exciting. To give you an idea of what I'm talking about, here's a log from a week I spent increasing the speed of our JavaScript library: Monday, November 18, 2002 - sped up JavaScript iBench by 70% by using a better sort algorithm and reducing the number of UString allocations - sped up JavaScript iBench by 6% by turning ExecState into a simple object instead of a two level abstraction - sped up JavaScript iBench by 7% by turning the property map into a hash table and improving String instance handling - sped up JavaScript iBench by 6% by hoisting the property map into ObjectImp and doing less ref/unref - sped up JavaScript iBench by 1.5% by converting integers into strings with custom code rather than sprintf Tuesday, November 19, 2002 - sped up JavaScript iBench by 2% by using masking instead of modulus in the property map hash table code - sped up JavaScript iBench by 3% by improving the implementation of the "perfect hashing" hash tables used for static properties - sped up JavaScript iBench by 1.5% by storing computed hash values in the UString representation so we don't recompute them - sped up JavaScript iBench by 6.5% by atomizing property identifiers - sped up JavaScript iBench by 1.5% by not clearing and rebuilding the list each time during sorting Wednesday, November 20, 2002 - sped up JavaScript iBench by 5% by decreasing the amount of ref/deref done by changing interfaces so they can deal directly with ValueImp - sped up JavaScript iBench by 1% by making lists ref/unref less - sped up JavaScript iBench by 7.5% by creating argument list objects only on demand rather than for each function call Thursday, November 21, 2002 - sped up JavaScript iBench by 3% by allocating the ActivationImp objects on the stack rather than in the garbage-collected heap - sped up JavaScript iBench by 11% by turning the scope chain into a singly-linked list that shares tails rather than a non-sharing doubly-linked list with subtly different semantics Friday, November 22, 2002 - sped up JavaScript iBench by 10% by changing the List class from a linked list to a vector, and using a pool of instances ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: class proposal
On Wednesday, Apr 23, 2003, at 16:07 America/Denver, Justin M. Lewis wrote: Sorry if the explanation is a bit confusing. The whole idea here is to make it explicit at the function invocation that a parameter being passed will be used to return a value. A good example of where this would be useful is with a function call that takes some params, and returns several different things in different params, and still has an explicit return for an error code. At the invocation point it would be impossible to tell what's going on. int chk; chk = GetSomething(p1, p2, p3, p4, p5); where the actual declaration of GetSomething is like int GetSomething(int &ret1, int &ret2, int v1, int v2, int v3); It's impossible to tell at the invocation which params are returning, and which are being used to calculate the return. At the invocation it looks like chk might be what you're trying to get. With classes like I'm suggesting it would be obvious, the declaration would be: int GetSomething(c_out ret1, c_out &ret2, int v1, int v2, int v3); And at the invocation now, it has to be explicit that those first 2 params are out params. chk = GetSomething(out(p1), out(p2), p3, p4, p5); It REQUIRES you to use the out helper function at the invocation, so anyone reading the code later can see, without checking the implementation of GetSomething, that those 2 params are being set, and the last ones are not. Is this really that much better than chk = GetSomething(&p1, &p2, p3, p4, p5); or GotSomething ret = GetSomething(p3,p4,p5); ? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: class proposal
On Wednesday, Apr 23, 2003, at 12:04 America/Denver, Terje Slettebø wrote: From: "Justin M. Lewis" <[EMAIL PROTECTED]> Well, I guess, based on all the code I've been reading at work it didn't seem so small, chasing down all kinds of functions across 100's of files to see why exactly values are changing mid function I'm looking at without warning. Anyway, this would allow for stronger enforcement of the rule that changing params should be marked somehow. As the programmer of a library people are using, I can force them to mark the params they're passing as out or in_out, so in 5 years when someone else comes along and has to debug it, it's all clear what's happening. Why not use T & if the function may change it, and const T & if it won't? Because looking at the call f(&x) I wonder what happens to x, whereas looking at the call f(x) I don't? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost