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<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);

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to