mesos-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jie Yu <yujie....@gmail.com>
Subject Re: using std::unique_ptr
Date Mon, 15 Dec 2014 18:23:00 GMT
To add to my previous email, the reason we cannot use Owned there is
because it's a public mesos header, and we don't wanna introduce extra
dependency to libprocess for frameworks.

On Mon, Dec 15, 2014 at 10:15 AM, Dominic Hamon <dhamon@twopensource.com>
wrote:
>
> I think that's a good use, though I think using emplace_back would be a
> better move when dealing with unique_ptr, assuming we have it in 4.4?
>
> On Fri, Dec 12, 2014 at 9:25 PM, Jie Yu <yujie.jay@gmail.com> wrote:
> >
> > Good start Dominic! I have another example which I think using unique_ptr
> > is preferred.
> >
> > We need to store a vector of pointers to the base class (which means we
> > have to use pointers here). However, storing raw pointer makes the
> > ownership tracking not explicit. What do you guys think?
> >
> >   // Base class.
> >   class Transformation
> >   {
> >   public:
> >     virtual ~Transformation() {}
> >
> >     virtual Try<Resources> apply(const Resources& resources) = 0;
> >   };
> >
> >   // Derived class. Use composite pattern.
> >   class CompositeTransformation : public Transformation
> >   {
> >   public:
> >     CompositeTransformation() {}
> >
> > *    void add(std::unique_ptr<Transformation> transformation)*
> > *    {   *
> > *      transformations.push_back(std::move(transformation));*
> > *    }   *
> >
> >     virtual Try<Resources> apply(const Resources& resources);
> >
> >   private:
> >     *std::vector<std::unique_ptr<Transformation>> transformations;*
> >   };
> >
> > On Fri, Dec 12, 2014 at 3:01 PM, Dominic Hamon
> <dhamon@twitter.com.invalid
> > >
> > wrote:
> > >
> > > Great idea.
> > >
> > > There is one place that immediately springs to mind that I think is
> > trivial
> > > but will get us used to the idea and exercise some of the demons: Unit
> > > tests. Within a test we regularly create some object on the heap and
> then
> > > delete it at the end of the test, or for the lifetime of a test
> fixture.
> > > All of these should be well scoped in lifetime and are prime targets
> for
> > > unique_ptr.
> > >
> > > On Wed, Dec 10, 2014 at 3:32 PM, Jie Yu <yujie.jay@gmail.com> wrote:
> > > >
> > > > Dominic,
> > > >
> > > > Thank you for brining this up! Instead of making a decision based on
> > high
> > > > level design and coding philosophy, I would really love to see some
> > > > concrete examples in our code base where we can start to use
> unique_ptr
> > > and
> > > > why it's better. Thoughts?
> > > >
> > > > - Jie
> > > >
> > > > On Wed, Dec 10, 2014 at 3:20 PM, Dominic Hamon <
> > dhamon@twopensource.com>
> > > > wrote:
> > > >
> > > > > Hello!
> > > > >
> > > > > We have access to std::unique_ptr, as many of you know, but we're
> not
> > > > using
> > > > > it. I'd like to start using it. Before we do, I'd like to discuss
> how
> > > we
> > > > > use it, when we use it, and things to be aware of.
> > > > >
> > > > > The style guide has the following to say (long quote, sorry):
> > > > >
> > > > > "
> > > > > Prefer to have single, fixed owners for dynamically allocated
> > objects.
> > > > > Prefer to transfer ownership with smart pointers.
> > > > >
> > > > > "Ownership" is a bookkeeping technique for managing dynamically
> > > allocated
> > > > > memory (and other resources). The owner of a dynamically allocated
> > > object
> > > > > is an object or function that is responsible for ensuring that it
> is
> > > > > deleted when no longer needed. Ownership can sometimes be shared,
> in
> > > > which
> > > > > case the last owner is typically responsible for deleting it. Even
> > when
> > > > > ownership is not shared, it can be transferred from one piece of
> code
> > > to
> > > > > another.
> > > > >
> > > > > "Smart" pointers are classes that act like pointers, e.g. by
> > > overloading
> > > > > the * and -> operators. Some smart pointer types can be used to
> > > automate
> > > > > ownership bookkeeping, to ensure these responsibilities are met.
> > > > > std::unique_ptr is a smart pointer type introduced in C++11, which
> > > > > expresses exclusive ownership of a dynamically allocated object;
> the
> > > > object
> > > > > is deleted when the std::unique_ptr goes out of scope. It cannot
be
> > > > copied,
> > > > > but can be moved to represent ownership transfer. std::shared_ptr
> is
> > a
> > > > > smart pointer type that expresses shared ownership of a dynamically
> > > > > allocated object. std::shared_ptrs can be copied; ownership of the
> > > object
> > > > > is shared among all copies, and the object is deleted when the last
> > > > > std::shared_ptr is destroyed.
> > > > >
> > > > > It's virtually impossible to manage dynamically allocated memory
> > > without
> > > > > some sort of ownership logic.
> > > > > Transferring ownership of an object can be cheaper than copying it
> > (if
> > > > > copying it is even possible).
> > > > > Transferring ownership can be simpler than 'borrowing' a pointer
or
> > > > > reference, because it reduces the need to coordinate the lifetime
> of
> > > the
> > > > > object between the two users.
> > > > > Smart pointers can improve readability by making ownership logic
> > > > explicit,
> > > > > self-documenting, and unambiguous.
> > > > > Smart pointers can eliminate manual ownership bookkeeping,
> > simplifying
> > > > the
> > > > > code and ruling out large classes of errors.
> > > > > For const objects, shared ownership can be a simple and efficient
> > > > > alternative to deep copying.
> > > > > Ownership must be represented and transferred via pointers (whether
> > > smart
> > > > > or plain). Pointer semantics are more complicated than value
> > semantics,
> > > > > especially in APIs: you have to worry not just about ownership, but
> > > also
> > > > > aliasing, lifetime, and mutability, among other issues.
> > > > > The performance costs of value semantics are often overestimated,
> so
> > > the
> > > > > performance benefits of ownership transfer might not justify the
> > > > > readability and complexity costs.
> > > > > APIs that transfer ownership force their clients into a single
> memory
> > > > > management model.
> > > > > Code using smart pointers is less explicit about where the resource
> > > > > releases take place.
> > > > > std::unique_ptr expresses ownership transfer using C++11's move
> > > > semantics,
> > > > > which are relatively new and may confuse some programmers.
> > > > > Shared ownership can be a tempting alternative to careful ownership
> > > > design,
> > > > > obfuscating the design of a system.
> > > > > Shared ownership requires explicit bookkeeping at run-time, which
> can
> > > be
> > > > > costly.
> > > > > In some cases (e.g. cyclic references), objects with shared
> ownership
> > > may
> > > > > never be deleted.
> > > > > Smart pointers are not perfect substitutes for plain pointers.
> > > > > If dynamic allocation is necessary, prefer to keep ownership with
> the
> > > > code
> > > > > that allocated it. If other code needs access to the object,
> consider
> > > > > passing it a copy, or passing a pointer or reference without
> > > transferring
> > > > > ownership. Prefer to use std::unique_ptr to make ownership transfer
> > > > > explicit. For example:
> > > > >
> > > > > std::unique_ptr<Foo> FooFactory();
> > > > > void FooConsumer(std::unique_ptr<Foo> ptr);
> > > > > Do not design your code to use shared ownership without a very good
> > > > reason.
> > > > > One such reason is to avoid expensive copy operations, but you
> should
> > > > only
> > > > > do this if the performance benefits are significant, and the
> > underlying
> > > > > object is immutable (i.e. std::shared_ptr<const Foo>). If you
do
> use
> > > > shared
> > > > > ownership, prefer to use std::shared_ptr.
> > > > >
> > > > > Do not use scoped_ptr in new code unless you need to be compatible
> > with
> > > > > older versions of C++. Never use std::auto_ptr. Instead, use
> > > > > std::unique_ptr.
> > > > > "
> > > > >
> > > > > Now I'm a big fan of explicit ownership and moving ownership rather
> > > than
> > > > > sharing non-smart pointers, but I recognise that in our code-base,
> > > > > ownership is difficult to reason about in many cases. However, we
> do
> > > have
> > > > > quite a few cases where we manage lifetime scope with explicit
> delete
> > > > calls
> > > > > and I'd like to start by eliminating those. Ie, using
> std::unique_ptr
> > > to
> > > > > manage lifetime not necessarily ownership.
> > > > >
> > > > > This is difficult though as we may pass these pointers to other
> > methods
> > > > or
> > > > > even other libprocess processes. In cases that we can reason about
> > the
> > > > > lifetime of the various pointers, that should be fine, but we have
> to
> > > be
> > > > > careful.
> > > > >
> > > > > One option is to start by replacing these pointers with
> > process::Owned.
> > > > The
> > > > > downside to this approach is that it introduces more non-standard
> > types
> > > > > and, because Owned is implemented using std::shared_ptr, doesn't
> move
> > > us
> > > > > closer to defining clear ownership.
> > > > >
> > > > > ​So the floor is open. Do we:
> > > > >
> > > > > 1) embrace std::unique_ptr, eliminate raw pointers except in rare,
> > > > > well-defined cases from a lifetime point of view?
> > > > > 2) eliminate raw pointers in favour of std::shared_ptr and
> > > > std::unique_ptr
> > > > > then work to eliminate the std::shared_ptrs
> > > > > 3) use process::Owned everywhere and then find places where we can
> > > > > transition them to std::unique_ptr
> > > > > 4) do nothing; there's no great benefit to std::unique_ptr and this
> > > smart
> > > > > pointer thing is just a fad.
> > > > >
> > > > >
> > > > > - dominic​
> > > > >
> > > > >
> > > > > --
> > > > > Dominic Hamon | @mrdo | Twitter
> > > > > *There are no bad ideas; only good ideas that go horribly wrong.*
> > > > >
> > > >
> > >
> > >
> > > --
> > > Dominic Hamon | @mrdo | Twitter
> > > *There are no bad ideas; only good ideas that go horribly wrong.*
> > >
> >
>
>
> --
> Dominic Hamon | @mrdo | Twitter
> *There are no bad ideas; only good ideas that go horribly wrong.*
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message