From: viboes on
Hello,

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>(new char[sizeof(C)]);
if (p==0) {
throw std::bad_alloc();
}
std::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

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
viboes wrote:
> 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

If you just want to copy the memory of an object, use this:

vector<char> m(sizeof o);
memcpy(&m[0], &o, sizeof o);

However, just having this memory is useless when it contains any pointers to
external storage or internal storage. With that in mind, I wonder where your
requirement to only copy the raw memory comes from.

> The following will create a deep copy and don't respect my
> requirements
>
> class C {
> public:
> C* shallow_clone() {
> return new C(*this);
> }
> };

If C actually is a POD, this boils down to a simple memcpy(). If C is not a
POD, a memcpy() wouldn't work, as mentioned above. So, you don't gain
anything from not doing it this way - unless of course there is some problem
to solve that you didn't explain here.

Note: It's sometimes better to ask for a solution to a problem than to ask
how to implement a very specific solution to that problem!

> C* shallow_clone() {
> C* p = reinterpret_cast<C>(new char[sizeof(C)]);
> if (p==0) {
> throw std::bad_alloc();
> }
> std::memcpy(p, this, sizeof(C));
> return p;
> }

The returned memory is not a C instance, so it shouldn't be a pointer to C!
I would rather return some handle to the memory and create a similar
function to restore the internal state from this memory, but this isn't
good.

> But I suspect that this is not correct in general. Is this correct on
> some particular cases? if yes on witch ones?

Apart from the unnecessary use of reinterpret_cast, the idea seems to be the
same as with the use of std::vector above.

> 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?

Yes. How to do that depends on what exactly you are trying to achieve, which
isn't clear yet.

Uli


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: viboes on
On Jan 4, 4:19 pm, Ulrich Eckhardt <dooms...(a)knuut.de> wrote:
> viboes wrote:
> > 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
>
> If you just want to copy the memory of an object, use this:
>
> vector<char> m(sizeof o);
> memcpy(&m[0], &o, sizeof o);

No I don't need just to copy the memory.

> However, just having this memory is useless when it contains any pointers to
> external storage or internal storage. With that in mind, I wonder where your
> requirement to only copy the raw memory comes from.

My context is Software Transactional Memory (STM). The shared
transactional objects need to be cached on transaction specific
objects. The pointers these transactional objects contains are
pointers to other transactional objects.

The idea I have in mind is that this cache don't need to do a deep
copy of the transactional object, but just a shallow copy, as the STM
system will take care of the copy of these pointee transactional
objects when modified. In addition I want the STM mechanism to
interfere as less as possible with the user space. That is why I don't
want to use copy constructor, assignment, neither class specific new/
delete operators.

> > The following will create a deep copy and don't respect my
> > requirements
>
> > class C {
> > public:
> > C* shallow_clone() {
> > return new C(*this);
> > }
> > };
>
> If C actually is a POD, this boils down to a simple memcpy(). If C is not a
> POD, a memcpy() wouldn't work, as mentioned above. So, you don't gain
> anything from not doing it this way - unless of course there is some problem
> to solve that you didn't explain here.

The only I see in the case the copy constructor is private, isn't it?

> Note: It's sometimes better to ask for a solution to a problem than to ask
> how to implement a very specific solution to that problem!
<snip>
> > 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?
>
> Yes. How to do that depends on what exactly you are trying to achieve, which
> isn't clear yet.

I will try to explain what I want to get as shortly as possible, but
it will be quite long.

The STM library I'm working on requires that any transactional object
inherits from

class base_transaction_object {
public:
virtual base_transaction_object*
make_cache(transaction* t) const = 0;
virtual void copy_cache(
base_transaction_object const * const) = 0;
virtual void delete_cache()=0;
virtual ~base_transaction_object() {};
...
};

I omit here why the STM library need this.

The same library defines a mixin class transaction_object using the
copy-constructor, the assignment operator and the new and delete
operators. This class is defined as follows:

template <
class Final,
class Base=base_transaction_object>
class transaction_object : public Base {
public:
base_transaction_object* make_cache() const
{
return new Final(this);
}
void delete_cache()
{
delete this;
}
void copy_cache(
base_transaction_object const * const rhs)
{
*static_cast<Final *>(this) =
*static_cast<Final const * const>(rhs);
}
};

Deep copy semantic liabilities: As the preceding transaction_object
class makes use of copy constructor, destructor and assignment
operator to manage the cache, if the class requires a deep copy, the
STM system will use the deep copy implementation. While deep copy is
needed for C++ classes with ownership on its members, it is not the
case with transaction specific cached objects owning other
transactional objects. Transaction specific cached objects are not
usual C++ objects, form the user perspective they don't exists at all,
they are seen as an implementation detail, so any allocation,
deallocation, copy from or copy to a transaction specific cached
object should not use the C++ new, delete, copy constructor or
assignment operator of the class.

The typical example of a class that can not be used with this mixin is
a non-copyable class and in particular any singleton class. An example
of a class on which the call to the constructor/destructor interferes
with the transactional world, is a class that don�t allows more than n
instances. If the cache instances are counted as instances of the
class, we couldn�t work with more than n-1 transactions.

Next follows an example of performance degradation:
struct Node {
tx::pointer<Node> next_; // this is a transactional pointer
};

class List : public transaction_object<List> {
std::size_t size_;
Node head_;
public:
// makes a deep-copy
List(List const& rhs);
// makes a deep-copy
List& operator=(List const& rhs);

};

As transaction_object is based on copy semantics, and the class List
owns all its elements, any change to the field size_ or head_ implies
the allocation of a transaction specific cache instance, a deep copy
of the complete list to the transaction specific cache before any
modification, and the deallocation this cached instance after the
transaction completes and possibly another copy from the cache to the
shared transactional object. Even if the implementation is correct, it
is clearly not efficient.

Form what you and others said, we can use std::memcpy instead of
calling to the CopyConstructor and the Assignment operator only for
classes that have a trivial copy constructor and a trivial assignment.
The STM system could provide also a trivial copy
trivial_transactional_object mixin applicable to classes for which
has_trivial_copy_semantics<C>::value is true.

template <class T>
struct has_trivial_copy_semantics :
boost::mpl::and_<
boost::has_trivial_copy_constructor<T>,
boost::has_trivial_assign<T>>
>
{};

template <
class Final,
class Base=base_transaction_object
>
class trivial_transaction_object
: public Base {
public:
base_transaction_object* make_cache() const
{
Final* p = cache_allocate<Final>(t);
std::memcpy(p,
static_cast<Final const*>(this),
sizeof(Final));
return p;
}
void delete_cache()
{
cache_deallocate(this);
}
void copy_cache(
base_transaction_object const * const rhs)
{
std::memcpy(static_cast<Final *>(this),
static_cast<Final const * const>(rhs),
sizeof(Final));
}
};
where
template <class T>
T* cache_allocate()
{
return reinterpret_cast<T*>(
new char[sizeof(T)]);
}
template <class T>
void cache_deallocate(T* ptr)
{
delete [] reinterpret_cast<char*>(ptr);
}

IMO there is no need to call the destructor of Final. The reason is
that this object is not a real one, is a cache of other real object.

For classes that have no trivial copy semantics we can yet do a
shallow copy, but as I understand it now, not without the help of
user. I'm wondering if it is worth to require the user to define the
following shallow functions:

struct shallow_t {};
const shallow_t shallow = {};

// Shallow copy constructor
C(C const&, shallow_t);
// Shallow assignement
C& shallow_assign(C const&);

STM could then provides also a shallow copy mixin.

template <
class Final,
class Base=base_transaction_object
>
class shallow_transactional_object
: public Base {
public:
base_transaction_object* make_cache() const
{
Final* p = cache_allocate<Final>(t);
return new(p) Final(this, shallow);
}
void delete_cache()
{
cache_deallocate(this);
}
void copy_cache(
base_transaction_object const * const rhs)
{
this->shallow_assign(
static_cast<Final const * const>(rhs));
}
};

Note that there is no need to call the destructor. The reason is the
same than the memcpy case. The single difference is that instead of
doing a single memcpy, we will do several ones or the equivalent. That
means that shallow copy should relay only on fundamental copies or use
shallow copy on its members.

Now we can define transaction_object that depends on whether the final
class has trivial, shallow or deep copy semantics.

namespace detail {
template <class Final, typename Base,
bool hasShallowCopySemantics,
bool hasTrivialCopySemantics>
class transactional_object;

template <class F, class B>
class transaction_object<F, B, true, true>:
public shallow_transaction_object<F, B> {};
template <class F, class B>
class transactional_object<F, B, true, true>:
public shallow_transaction_object<F, B> {};
template <class F, class B>
class transactional_object<F, B, false, true>:
public trivial_transaction_object<F, B> {};
template <class F, typename B>
class transactional_object<F, B, false, false>:
public deep_transaction_object<F, B> {};
}
template <
class Final,
class Base=base_transaction_object
> class transaction_object
: public detail::transaction_object<
Final, Base,
has_shallow_copy_semantics<Final>::value,
has_trivial_copy_semantics<Final>::value
>
{};

(deep_transaction_object corresponds to the initial transaction_object
class)

I don't know how to implement has_shallow_copy_semantics<T>::value, in
a portable way.

template <class T>
struct has_shallow_copy_semantics : boost::mpl::false_ {};

The user will need to specialize this template as follows

template <>
struct has_shallow_copy_semantics<C> : boost::mpl::true_ {};


With all this stuff I can define the list example avoiding the
performance degradation as follows

class List : public transactional_object<List>
{
std::size_t size_;
Node head_;
public:
// shallow copy constructor
List( List const& rhs, stm::shallow_t)
: size_(rhs.size_)
, head_(rhs.head_)
{}
// shallow assignment
List& shallow_assign( List const& rhs) {
if (*this!=rhs) {
size_=rhs.size_;
head_=rhs.head_;
}
return *this;
}
// makes a deep-copy
List(List const& rhs);
// makes a deep-copy
List& operator=(List const& rhs);

};

template <>
struct has_shallow_copy_semantics<List> : boost::mpl::true_ {};

Note that even if the following are public
List( List const& rhs, stm::shallow_t)
List& shallow_assign( List const& rhs) {

they are intended to be used only by
shallow_transactional_object<List>

Hopping this explain the problem I want to solve, and how I try to
solve it now. Please let me know if there is a flaw on this design, or
any hint to make this better, more portable.

Best.
Vicente

P.S. The code included in this post has evidently not been compiled :(


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Jan 3, 5:54 pm, viboes <vicente.bo...(a)wanadoo.fr> wrote:
> Hello,
>
> 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);
> }
>
> };

Let's get terminology clear first... Deep versus shallow copy is
usually explained like this: http://en.wikipedia.org/wiki/Object_copy

What strikes me as strange is that you are employing operator new.
This is unwarranted when speaking only about deep/shallow copy
distinction. So the way to make what is commonly known as a deep copy
is both

C copy(original);

AND

C* pcopy = new C(original);

IOW, storage doesn't matter, at least unless you start with derivation
and polymorphism.

Shallow copy means that you want a copy where only part of original
instance data. Typically, in a shallow copy, you don't want a copy of
embedded or pointed-to objects. For that, there is no mechanism in C+
+, and trying to use memcpy is most usually a HUGE MISTAKE: you are
e.g. creating dangling pointers, you are breaking reference counting
for objects that do it, (strings come to mind) etc.

So the problem with shallow copy is that "shallow" means different
things in different contexts, that is, which class members are
"shallow", and which are "deep". That's for your design to decide.
Consequence of that is that you have to create your own shallow copy
function and avoid standard copy constructors and assignments. They
are most usually deep copies, so leave them for that.



Conclusion:

You have only one reasonable path: decide what constitutes a "shallow"
copy and make a function that does that, e.g.

class shallow_piece
{
int i, j, k; // Shallow
};

class C
{
shallow_piece shallow;
vector<other_class> deep;

// Special conversion ctor that acts as a shallow-copy-ctor.
// If shallow_piece is POD, it's effectively as fast as memcpy.
C(const shallow_piece& original) : shallow(original) {}
};

and then:

C original;
C shallow_copy(original.shallow);
C deep_copy(original);

I repeat: whether the result is on the heap or not is orthogonal to
the question of deep versus shallow. But, if you have derivation, then
it's very likely that shallow_piece idea is less useful. You then have
to have shallow_copy function that returns heap-based instances, and
each derived class decides what members are shallow (typically, it
will take base class "shallow members" and add one or two of it's
own). You can still employ shallow_piece idea e.g. like this, at a
cost of using heap for "shallow" part:

class shallow_piece_base {etc.};

class C_base
{
shallow_piece_base* p_shallow;
virtual C_base* shallow_copy() const;
};

class shallow_piece_derived : public shallow_piece_base {etc.};

class C : public C_base
{
// inherited p_shallow always points to shallow_piece_derived.
C(const shallow_piece_derived& shallow) : p_shallow(new
shallow_piece_derived(shallow)) {}
virtual C_base* shallow_copy() const { return new C_base
(*p_shallow); };
};

If your concern is speed, there's two things to consider: measure
whether it's faster to copy stuff around or to share heap pointers.
But that __hugely__ depends on data sizes and your actual code the way
it's running "in production" (that is, a simple test program might be
misleading).

>
> 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>(new char[sizeof(C)]);
> if (p==0) {
> throw std::bad_alloc();

That p==0 is just poor C++. new throws unless nothrow is used.

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: viboes on
On Jan 5, 8:17 pm, Goran <goran.pu...(a)gmail.com> wrote:
> On Jan 3, 5:54 pm, viboes <vicente.bo...(a)wanadoo.fr> wrote:
>
>
>
> > Hello,
>
> > 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);
> > }
>
> > };
>
> Let's get terminology clear first... Deep versus shallow copy is
> usually explained like this:http://en.wikipedia.org/wiki/Object_copy

I know. This is exactly how I'm using the shallow word.

> What strikes me as strange is that you are employing operator new.
> This is unwarranted when speaking only about deep/shallow copy
> distinction. So the way to make what is commonly known as a deep copy
> is both
>
> C copy(original);
>
> AND
>
> C* pcopy = new C(original);
>
> IOW, storage doesn't matter, at least unless you start with derivation
> and polymorphism.

Sorry if my text let you think I was saying that storage matter when
making the difference between deep and shallow copy. It was not my
intention.

> Shallow copy means that you want a copy where only part of original
> instance data. Typically, in a shallow copy, you don't want a copy of
> embedded or pointed-to objects. For that, there is no mechanism in C+
> +, and trying to use memcpy is most usually a HUGE MISTAKE: you are
> e.g. creating dangling pointers, you are breaking reference counting
> for objects that do it, (strings come to mind) etc.

In my use case, there is no dangling pointer, as the shallow copied
objects are cache of other shared objects. In a general case it is
clear that deep copy should be used when the class owns the reference
object. In my last post I explain widely the context.

> So the problem with shallow copy is that "shallow" means different
> things in different contexts, that is, which class members are
> "shallow", and which are "deep". That's for your design to decide.
> Consequence of that is that you have to create your own shallow copy
> function and avoid standard copy constructors and assignments. They
> are most usually deep copies, so leave them for that.

I agree. This was one of the motivations to don't use them.

> Conclusion:
>
> You have only one reasonable path: decide what constitutes a "shallow"
> copy and make a function that does that, e.g.
>
> class shallow_piece
> {
> int i, j, k; // Shallow
>
> };
>
> class C
> {
> shallow_piece shallow;
> vector<other_class> deep;
>
> // Special conversion ctor that acts as a shallow-copy-ctor.
> // If shallow_piece is POD, it's effectively as fast as memcpy.
> C(const shallow_piece& original) : shallow(original) {}
>
> };
>
> and then:
>
> C original;
> C shallow_copy(original.shallow);
> C deep_copy(original);

This could work. I have opted for a different solution. See my last
post.

> I repeat: whether the result is on the heap or not is orthogonal to
> the question of deep versus shallow. But, if you have derivation, then
> it's very likely that shallow_piece idea is less useful. You then have
> to have shallow_copy function that returns heap-based instances, and
> each derived class decides what members are shallow (typically, it
> will take base class "shallow members" and add one or two of it's
> own). You can still employ shallow_piece idea e.g. like this, at a
> cost of using heap for "shallow" part:
>
> class shallow_piece_base {etc.};
>
> class C_base
> {
> shallow_piece_base* p_shallow;
> virtual C_base* shallow_copy() const;
>
> };
>
> class shallow_piece_derived : public shallow_piece_base {etc.};
>
> class C : public C_base
> {
> // inherited p_shallow always points to shallow_piece_derived.
> C(const shallow_piece_derived& shallow) : p_shallow(new
> shallow_piece_derived(shallow)) {}
> virtual C_base* shallow_copy() const { return new C_base
> (*p_shallow); };
>
> };

This introduce an indirection that I would avoid.

> If your concern is speed, there's two things to consider: measure
> whether it's faster to copy stuff around or to share heap pointers.
> But that __hugely__ depends on data sizes and your actual code the way
> it's running "in production" (that is, a simple test program might be
> misleading).

I'm doing a library that could improve its performance when the
template parameter type has ShallowCopy semantics. So I will let this
decision to the user. Thanks anyway for your suggestions.

> > 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>(new char[sizeof(C)]);
> > if (p==0) {
> > throw std::bad_alloc();
>
> That p==0 is just poor C++. new throws unless nothrow is used.

You are right. :)

Could you comment on the approach I have presented on my last post?
Best,
Vicente


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]