Boost logo

Boost :

Subject: Re: [boost] How to create a shallow copy without calling aconstructor?
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-01-02 17:34:51


----- Original Message -----
From: "Stefan Strasser" <strasser_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Saturday, January 02, 2010 5:14 PM
Subject: Re: [boost] How to create a shallow copy without calling aconstructor?

>
> Am Saturday 02 January 2010 16:42:45 schrieb vicente.botet:
>> I have looked at uninitialized_copy but if I have understood it correctly,
>> it calls the copy constructor. I have tried with
>>
>> class C {
>> public:
>> C* shallow_clone() {
>> C* p = reinterpret_cast<C>(malloc(sizeof(C));
>> if (p==0) {
>> throw std::bad_alloc();
>> }
>> memcpy(p, this, sizeof(C));
>> return p;
>> }
>> };
>>
>> But I suspect that this is not correct in general. Is this correct on some
>> particular cases? if yes on witch ones? Is there a way to create such a
>> cache instance without calling to the constructor in a portable way using
>> some low level C++ interface?
>
> new char[sizeof(T)], reinterpret_cast and std::memcpy().
> the C++ standard explicitely requires char-arrays to be aligned appropriately
> for objects of any type that fits in the array.
>
> I don't know the requirements of your cache, but there are many cases were
> copying an object like this will fail. e.g. when the object contains a
> boost::interprocess::offset_ptr, so this is only a portable way to copy PODs.

Hi,
I don't want to require the transactional object to be Copy-Constructible, but I need to copy it in the transactional specific cache. In addition I don't want the constructor/destructor of these copied cache instances to interfere on the user space.

What I want is avoid requiring the user to defines a specific shallow copy constructor and a specific shallow copy assignement. The base class of all the transactional objects in Boost.STM is
 
  class base_transaction_object {
  public:
    virtual base_transaction_object* shallow_clone() const = 0;
    virtual void copy_state(base_transaction_object const * const) = 0;
    virtual void cache_deallocate()=0;
    virtual ~base_transaction_object() {};
    ...
  };

The user can define a shallow copy himself as follows

class C : public base_transaction_object {
    C(C const& rhs, shallow_copy_t) {
    // do a shallow copy
    }
public:
  base_transaction_object* shallow_clone() {
     C* p = reinterpret_cast<C>(new char[sizeof(C)]);
      return new (p) C(*this, shallow_copy);
  }
  void copy_state(base_transaction_object const * const rhs) {
    // do a shallow assignement
  }
  void cache_deallocate() {
        delete[] reinterpret_cast<char*>(this);
  }
};

I want to define a generic mixin that define these function, something like:
 
  template <class Derived, typename Base=base_transaction_object>
  class shallow_transaction_object : public Base
  {
    typedef Base base_type;
  public:
    base_transaction_object* shallow_clone() const {
      Derived* p = reinterpret_cast<Derived*>( new char[sizeof(Derived)]);
      std::memcpy(p, static_cast<Derived const*>(this), sizeof(Derived));
      return p;
    }

    void cache_deallocate() {
        delete[] reinterpret_cast<char*>(this);
    }

    void copy_state(base_transaction_object const * const rhs) {
      std::memcpy(static_cast<Derived *>(this), static_cast<Derived const * const>(rhs), sizeof(Derived ));
    }
  };
  
So the user can just declare its own class as

 class C : public shallow_transaction_object<C> {
    // members concerning the user space
 };

Can this be done in a portable way?

Best,
Vicente


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