How to create a shallow copy without calling a constructor?

Hello, While developing Boost.STM (Software Transactional Memory), I need to create a cache of a transactional object without using the new operator nor the copy constructor of the class. This cache needs only to copy the raw memory of the copied instance, is for that I have called it shallow_clone The following will create a deep copy and don't respect my requirements class C { public: C* shallow_clone() { return new C(*this); } }; 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? Thanks, Vicente _____________________ Vicente Juan Botet Escribá

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.

----- Original Message ----- From: "Stefan Strasser" <strasser@uni-bremen.de> To: <boost@lists.boost.org> 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

vicente.botet wrote:
----- Original Message ----- From: "Stefan Strasser" <strasser@uni-bremen.de> To: <boost@lists.boost.org> 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
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Am Saturday 02 January 2010 23:34:51 schrieb vicente.botet:
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?
depends on if you really mean portable or "defined" (by C++ standard). I doubt memcpy()ing objects with a virtual pointer is defined, but I think it'll work on all implementations I know of if you always copy the most derived type. what types can class C : shallow_transaction_object contain? can it contain pointers or is it limited to "shallow types"? for the latter, you might want to make the decision if memcpy() can be used based on boost::serialization::is_bitwise_serializable. is the object in the cache used or is it only stored to be copied back to the exact same position of the original object, in case the transaction fails?

Hi Stefan, thanks for your comments ----- Original Message ----- From: "Stefan Strasser" <strasser@uni-bremen.de> To: <boost@lists.boost.org> Sent: Sunday, January 03, 2010 4:55 AM Subject: Re: [boost] How to create a shallow copy without callingaconstructor?
Am Saturday 02 January 2010 23:34:51 schrieb vicente.botet:
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 { 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?
depends on if you really mean portable or "defined" (by C++ standard).
I meant portable.
I doubt memcpy()ing objects with a virtual pointer is defined, but I think it'll work on all implementations I know of if you always copy the most derived type.
This will always be the case. I should rename the template parameter Derived by Final. template <class Final, typename Base=base_transaction_object> class shallow_transaction_object;
what types can class C : shallow_transaction_object contain? can it contain pointers or is it limited to "shallow types"?
it can contain any non pointer type and pointers to transactional objects, but no pointer to non-transactional objects. The pointee transactional objects do not need to be copied since the STM system track any modification to them.
for the latter, you might want to make the decision if memcpy() can be used based on boost::serialization::is_bitwise_serializable.
is_bitwise_serializable don't goes too far. it is equivalent to is_artithmetic. But it can be specialized. I have find in Boost.TypeTraits this example An Optimized Version of std::copy Demonstrates a version of std::copy that uses has_trivial_assign to determine whether to use memcpy to optimise the copy operation. maybe I need something like has_trivial_copy and has_trivial_assign.
is the object in the cache used or is it only stored to be copied back to the exact same position of the original object, in case the transaction fails?
This depends on the updating policy. With direct updating the cached objects is used as a backup and used to restablish the shared object in case of rollback, so it is never used directly, with deferred updating, the cached object is the object modified by the transaction and used to update the shared object in case of succesfull commit. For what you and Mathias said, and as I suspected the code is neither portable nor correct and limited to types having trivial copy semantics. template <class Derived, typename Base=base_transaction_object> class trivial_transactional_object : public Base { typedef Base base_type; public: base_transaction_object* make_cache() const { Derived* p = reinterpret_cast<Derived*>( new char[sizeof(Derived)]); std::memcpy(p, static_cast<Derived const*>(this), sizeof(Derived)); return p; } void remove_cache() { delete[] reinterpret_cast<char*>(this); } void copy_cache(base_transaction_object const * const rhs) { std::memcpy(static_cast<Derived *>(this), static_cast<Derived const * const>(rhs), sizeof(Derived )); } }; For shallow copy semantics, I suspect that I will need to relay on whether the user defines these shallow copy constructor and assignement operations following these prototypes struct shallow_t {}; const shallow_t shallow = {}; C(C const&, shallow_t); C& shallow_assign(C const&); The new shallow_transactional_object could be defined as template <class Derived, typename Base=base_transaction_object> class shallow_transactional_object : public Base { public: base_transaction_object* make_cache() const { Derived* p = reinterpret_cast<Derived*>( new char[sizeof(Derived)]); return new(p) Derived(this, shallow); } void remove_cache() { delete[] reinterpret_cast<char*>(this); } void copy_cache(base_transaction_object const * const rhs) { this->shallow_assign(static_cast<Derived const * const>(rhs)); } }; Now I can define transactional_object depending on whether has_trivial_copy_semantics<T>::value , has_shallow_copy_semantics<T>::value, or has_deep_copy_semantics<T>::value (TBD) namespace detail { template <class Final, typename Base, bool hasShallowCopySemantics, bool hasTrivialCopySemantics> class transactional_object; template <class Final, typename Base> class transactional_object<Final, Base, true, true>: public shallow_transactional_object<Derived, Base> {}; template <class Final, typename Base> class transactional_object<Final, Base, true, true>: public shallow_transactional_object<Derived, Base> {}; template <class Final, typename Base> class transactional_object<Final, Base, false,true>: public trivial_transactional_object<Derived, Base> {}; template <class Derived, typename Base> class transactional_object<Final, Base, false,false>: public deep_transactional_object<Derived, Base> {}; } template <class Final, typename Base=base_transaction_object> class transactional_object : public detail::transactional_object<Final, Base, has_shallow_copy_semantics<Derived>::value, has_trivial_copy_semantics<Derived>::value> {}; Of course, this force the user to define specific shallow copy semantics operations, but IMO this will have some advantages. What do you think of this approach? Anyway, I find that it is a shame that the compiler know how to make a shallow copy-constructor and shallow assignement operator, but one the user defines a specific one we are unable to use them. Do you think that its is worth to have the possibility to use the default generated constructors and assignement operators in C++ ? For example we could use these defaulted operators as follows C a(default); // use the default constructor generated by the compiler ... C b(a, default); // use the default copy constructor generated by the compiler C c; std::assign_default(c, a); // use the default assignement operator generated by the compiler for class C Best, Vicente

Am Sunday 03 January 2010 18:59:24 schrieb vicente.botet:
it can contain any non pointer type and pointers to transactional objects, but no pointer to non-transactional objects. The pointee transactional objects do not need to be copied since the STM system track any modification to them.
aren't you then really looking for a deep copy, excluding pointers to transactional objects? unfortunately there is no such concept of a "deep copy" in c++ either, so my approach is to use Boost.Serialization for cloning objects (or a user-supplied function). Using serialization you can decide on a case to case basis if the object behind a pointer should be copied. (depending on if the type is transactional, in your case). of course, that'd introduce the Serializable requirement and I don't know how well that fits into your design.
for the latter, you might want to make the decision if memcpy() can be used based on boost::serialization::is_bitwise_serializable.
is_bitwise_serializable don't goes too far. it is equivalent to is_artithmetic. But it can be specialized.
I have find in Boost.TypeTraits this example
I don't think you can use type traits to make sure an object doesn't have pointers (to non-transactional memory). I think you'll have to rely on the user to provide that information.
Of course, this force the user to define specific shallow copy semantics operations, but IMO this will have some advantages. What do you think of this approach?
how do you detect if a type provides this shallow copy constructor? as far as I know there is no way to statically detect that, that's why I went with inline friend functions, that can be found via ADL: https://svn.boost.org/svn/boost/sandbox/persistent/libs/persistent/doc/html/... this may be different in your case though because of the requirement to derive from *_transaction_object, that could be used to detect which types ought to provide a special copy constructor.

Stefan Strasser-2 wrote:
Am Sunday 03 January 2010 18:59:24 schrieb vicente.botet:
it can contain any non pointer type and pointers to transactional objects, but no pointer to non-transactional objects. The pointee transactional objects do not need to be copied since the STM system track any modification to them.
aren't you then really looking for a deep copy, excluding pointers to transactional objects?
yes, this could be said this way. Stefan Strasser-2 wrote:
unfortunately there is no such concept of a "deep copy" in c++ either, so my approach is to use Boost.Serialization for cloning objects (or a user-supplied function). Using serialization you can decide on a case to case basis if the object behind a pointer should be copied. (depending on if the type is transactional, in your case). of course, that'd introduce the Serializable requirement and I don't know how well that fits into your design.
Non , serialization don't fits my requirements as I need to use the object when deferred updating policy is used. Stefan Strasser-2 wrote:
for the latter, you might want to make the decision if memcpy() can be used based on boost::serialization::is_bitwise_serializable.
is_bitwise_serializable don't goes too far. it is equivalent to is_artithmetic. But it can be specialized.
I have find in Boost.TypeTraits this example
I don't think you can use type traits to make sure an object doesn't have pointers (to non-transactional memory). I think you'll have to rely on the user to provide that information.
I was talking of has_trivial_copy and has_trivial_assign. Anyway, if the user provides a fusion sequence view of the structure, we can decide if the structure has pointers to non-transactional objects. Stefan Strasser-2 wrote:
Of course, this force the user to define specific shallow copy semantics operations, but IMO this will have some advantages. What do you think of this approach?
how do you detect if a type provides this shallow copy constructor? as far as I know there is no way to statically detect that,
I know that this cannot be detected. And the user will need to specialize the trait. Stefan Strasser-2 wrote:
that's why I went with inline friend functions, that can be found via ADL: https://svn.boost.org/svn/boost/sandbox/persistent/libs/persistent/doc/html/...
Do you mean that I can request instead of the shallow copy constructor request a make_shallow_copy? C* make_shallow_copy(C const &); Stefan Strasser-2 wrote:
this may be different in your case though because of the requirement to derive from *_transaction_object, that could be used to detect which types ought to provide a special copy constructor.
Sorry, I don't understand how the fact the type must derive from base_transaction_object can help to define the has_shallow_copy_constructor. Could you elaborate? Thanks for your comments, Vicente -- View this message in context: http://old.nabble.com/How-to-create-a-shallow-copy-without-calling-a-constru... Sent from the Boost - Dev mailing list archive at Nabble.com.

Am Monday 04 January 2010 10:12:03 schrieb Vicente Botet Escriba:
Stefan Strasser-2 wrote:
unfortunately there is no such concept of a "deep copy" in c++ either, so my approach is to use Boost.Serialization for cloning objects (or a user-supplied function). Using serialization you can decide on a case to case basis if the object behind a pointer should be copied. (depending on if the type is transactional, in your case). of course, that'd introduce the Serializable requirement and I don't know how well that fits into your design.
Non , serialization don't fits my requirements as I need to use the object when deferred updating policy is used.
I didn't mean using the serialized stream, you can create deep copies using Boost.Serialization: serialize the object to memory and then deserialize it. if you keep the object that was used for serialization you have a clone, that is a deep copy by definition because boost.serialization is designed to reconstruct the exact same object graph that was used for serialization. by writing your own serialization archive you could make pointers to transactional objects shared among the clones.
Stefan Strasser-2 wrote:
this may be different in your case though because of the requirement to derive from *_transaction_object, that could be used to detect which types ought to provide a special copy constructor.
Sorry, I don't understand how the fact the type must derive from base_transaction_object can help to define the has_shallow_copy_constructor.
no, the user does have to express in some detectable way that he has a implemented a special copy constructor (if it is optional). this could be a type trait, or a special base class instead of transaction_object, that can be checked for using a standard type trait. (that's what I meant above). or you could use inline friend functions like I do, because I wanted to avoid a user-defined trait: template<class T> T *clone(T const &original){ //default implementation } class user_type{ friend user_type *clone(user_type const &original){ //user-supplied implementation } }; int main(){ user_type t1; other_user_type t2; clone(t1); //calls user-supplied implementation clone(t2); //calls default implementation }

Stefan Strasser-2 wrote:
Am Monday 04 January 2010 10:12:03 schrieb Vicente Botet Escriba:
Stefan Strasser-2 wrote:
unfortunately there is no such concept of a "deep copy" in c++ either, so my approach is to use Boost.Serialization for cloning objects (or a user-supplied function). Using serialization you can decide on a case to case basis if the object behind a pointer should be copied. (depending on if the type is transactional, in your case). of course, that'd introduce the Serializable requirement and I don't know how well that fits into your design.
Non , serialization don't fits my requirements as I need to use the object when deferred updating policy is used.
I didn't mean using the serialized stream, you can create deep copies using Boost.Serialization: serialize the object to memory and then deserialize it.
if you keep the object that was used for serialization you have a clone, that is a deep copy by definition because boost.serialization is designed to reconstruct the exact same object graph that was used for serialization.
by writing your own serialization archive you could make pointers to transactional objects shared among the clones.
Definitely I will not use Boost.Serialization for STM. Stefan Strasser-2 wrote:
Stefan Strasser-2 wrote:
this may be different in your case though because of the requirement to derive from *_transaction_object, that could be used to detect which types ought to provide a special copy constructor.
Sorry, I don't understand how the fact the type must derive from base_transaction_object can help to define the has_shallow_copy_constructor.
no, the user does have to express in some detectable way that he has a implemented a special copy constructor (if it is optional). this could be a type trait, or a special base class instead of transaction_object, that can be checked for using a standard type trait. (that's what I meant above).
or you could use inline friend functions like I do, because I wanted to avoid a user-defined trait:
template<class T> T *clone(T const &original){ //default implementation }
class user_type{ friend user_type *clone(user_type const &original){ //user-supplied implementation } };
int main(){ user_type t1; other_user_type t2;
clone(t1); //calls user-supplied implementation clone(t2); //calls default implementation }
Thanks for the friend to the free function hint, I will use the free function when the class is know statically. Obviously this can not be used when it is know at run-time so in this case I will use the virtual function. Both functions will be needed, but the virtual function can be defined by a mixin that call the static function. Vicente -- View this message in context: http://old.nabble.com/How-to-create-a-shallow-copy-without-calling-a-constru... Sent from the Boost - Dev mailing list archive at Nabble.com.

Am Saturday 02 January 2010 23:34:51 schrieb vicente.botet:
Derived* p = reinterpret_cast<Derived*>( new char[sizeof(Derived)]); std::memcpy(p, static_cast<Derived const*>(this), sizeof(Derived)); return p; }
quick question about this, is it legal to do the following? T *t=reinterpret_cast<T *>(new char[sizeof(T)]); new (&t) T; delete T; Boost.Serialization must use that, as it passes unconstructed memory to load_construct_data but lets the user "delete" the object, so I figure it must be ok. am I right? my platform (with valgrind) doesn't have a problem with it, but is it defined to be ok or portable among all known platforms?

Stefan Strasser wrote:
quick question about this, is it legal to do the following?
T *t=reinterpret_cast<T *>(new char[sizeof(T)]); new (&t) T; delete T;
No, because memory allocated with new[] must be deallocated with delete[]. T *t=static_cast<T *>( operator new( sizeof(T) ) ); takes care of this. There'd still be a mismatch if T had class-specific operator new/delete though, unless one is careful to use ::delete.

vicente.botet wrote:
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; } };
Or, maybe more appropriate, C* shallow_clone() { C* p = static_cast<C*>(::operator new(sizeof(C))); memcpy(p, this, sizeof(C)); return p; }
participants (6)
-
Mathias Gaunard
-
Michael
-
Peter Dimov
-
Stefan Strasser
-
Vicente Botet Escriba
-
vicente.botet