Boost logo

Boost :

From: Gregory Colvin (gregory.colvin_at_[hidden])
Date: 2003-08-29 01:05:40


On Thursday, Aug 28, 2003, at 23:48 America/Denver, E. Gladyshev wrote:
> --- Gregory Colvin <gregory.colvin_at_[hidden]> 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<int> a;
>
> {
> shared_ptr<int> 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<class Y, class D, class A>
>> shared_ptr(T* p, D d, const A& a)
>> : px(p), pn(p, d, A::rebind<<detail::sp_counted_base_impl<Data*,D>
>>> (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<typename Data, template<class>
>>> class Allocator>
>>> shared_ptr(
>>> Data*,
>>> Allocator<Data>,
>>> const Allocator<boost::detail::sp_counted_base_impl<Data*,
>>> Deleter> >& );
>>
>> 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<class Allocator,typename Data>
>> shared_ptr<T>
>> 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<Data>(p,deleter<Data>(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<T>
> {
> void operator()(T* d)
> {
> try
> {
> d->~T();
> }
> catch(...)
> {
> deallocate(d, 1);
> throw std::runtime_error("");
> }
> deallocate(d, 1);
> return;
> }
> };
>
>
> shared_ptr<Data> s( p, my_allocator<Data>(), 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<Data> s( p, my_allocator<Data>(),
> my_allocator<p,my_allocator<Data> >() );
>
> or there is another way?

my_allocator<Data> a;

shared_ptr<Data> s(p,a,a);


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk