If you think this is a significant ease of use benefit, why have to invoke 
move? I understand this code, but I have not seen it in recent memory.
I agree that this may make use of a copy(move) constructor easier, but...

If the consensus is that this is a significant ease of use benefit for the 
user, I am on board…

+1

Thanks,
Mark
> On Sep 18, 2017, at 11:15 AM, David Kimura <dkim...@pivotal.io> wrote:
> 
> The benefit I see isn't for performance, it's flexibility and ease of use
> by application developer.  Anything we can do to achieve this, I think is a
> significant win.
> 
> I think the reason for the various approaches is to determine whether we
> can safely create the simple/flexible API without incurring a penalty on
> performance.  Personally, I think the no nullptr benefit that Sarge
> mentioned in previous thread is enough to warrant this approach serious
> thought even though it provides no performance benefit.
> 
> Thanks,
> David
> 
> On Mon, Sep 18, 2017 at 10:47 AM, Mark Hanson <mhan...@pivotal.io> wrote:
> 
>> Hi All,
>> 
>> As we are creating a user API, unless there is a significant performance
>> benefit, I think we should try to take the simpler route.
>> 
>> I see benefit to the approach being proposed, but I don’t see a
>> significant benefit. Someone please school me if I am wrong.
>> 
>> I am still in the shared pointer camp for cache and a raw pointer to cache
>> in cacheImpl.
>> 
>> Sorry, and thanks,
>> Mark
>> 
>> 
>> 
>>> On Sep 18, 2017, at 10:14 AM, David Kimura <dkim...@pivotal.io> wrote:
>>> 
>>> +1 value approach (via some implementation from this thread)
>>> 
>>> I think I like this.
>>> 
>>> In all BAD cases, it's the user who shot themselves in the foot by using
>>> std::move unsafely.  I expect this behavior is the same behavior as for
>> any
>>> other object.  And if we're ever able to get rid of the Cache/CacheImpl
>>> circular dependency then we can add a copy constructor.
>>> 
>>> I also like the idea of passing in a CacheConfig.  My concern though is
>>> that it's piling on another big change.
>>> 
>>> Thanks,
>>> David
>>> 
>>> On Sun, Sep 17, 2017 at 12:02 AM, Jacob Barrett <jbarr...@pivotal.io>
>> wrote:
>>> 
>>>> Ok, one more idea.
>>>> https://gist.github.com/pivotal-jbarrett/beed5f70c1f3a238cef94832b13dab
>> 7a
>>>> 
>>>> The biggest issue with the value model is that we have been using a
>> factory
>>>> to build the Cache object. We really don't need one and if we get rid
>> of it
>>>> things look much better. They aren't perfect since we still need the
>> back
>>>> pointer from the impl to the cache for later use. If we didn't need that
>>>> then we could allow copy construction. As it stands right now this
>> version
>>>> allows value, shared_prt, unique_ptr, etc. without any real overhead or
>> RVO
>>>> issues.
>>>> 
>>>> The big change is that, rather than have a factory that we set a bunch
>> of
>>>> values on and then ask it to create the Cache, we create a CacheConfig
>>>> object and pass that in to the Cache's constructor. Cache passes it to
>>>> CacheImpl and CacheImpl sets itself up based on the config. If you look
>> at
>>>> what the current factory model does it isn't that different. For
>> clarity I
>>>> added an XmlCacheConfig object to that builds up the CacheConfig via
>> Xml.
>>>> You could imagine a YamlCacheConfig object *shiver*. The point is we
>> don't
>>>> care as long as we get a CacheConfig with all the things we support at
>>>> "init" time.
>>>> 
>>>> I know it is a more radical change but I feel it is more C++ and more
>>>> testable than the factory model. I also like that it solves some of the
>>>> issues with the value model we were looking at.
>>>> 
>>>> -Jake
>>>> 
>>>> On Thu, Sep 14, 2017 at 5:16 PM Jacob Barrett <jbarr...@pivotal.io>
>> wrote:
>>>> 
>>>>> Y'all here is an attempt to get the best of both worlds.
>>>>> https://gist.github.com/pivotal-jbarrett/
>> 52ba9ec5de0b494368d1c5282ef188
>>>> ef
>>>>> 
>>>>> I thought I would try posting to Gist but so far not impressed, sorry.
>>>>> 
>>>>> The Gist of it is that we can overcome the thirdpary or transient
>>>>> reference back to the public Cache instance by keeping a reference to
>> it
>>>> in
>>>>> the implementation instance and updating it whenever the move
>> constructor
>>>>> is called.
>>>>> 
>>>>> The downside is if your run this test it doesn't show RVO kicking in on
>>>>> the second test where we move the value into a shared pointer. There
>> are
>>>> a
>>>>> couple of pitfalls you can stumble into as well by trying to used the
>>>>> previous instance to access the cache after the move operation, as
>>>>> illustrated by the "BAD" commented lines.
>>>>> 
>>>>> The upside is the choices this gives the use for ownership of their
>>>>> factory constructed Cache instance. They can keep it a value or move it
>>>> to
>>>>> unique or shared pointer.
>>>>> 
>>>>> Overhead wise I think we better off in value as long as there are no
>>>>> moves, rare I would thing, but the moves are pretty cheap at the point
>>>>> since we only maintain a unique_ptr. After moving into a shared_ptr it
>>>> acts
>>>>> identical to the shared_ptr model proposed earlier.
>>>>> 
>>>>> -Jake
>>>>> 
>>>>> 
>>>>> On Thu, Sep 14, 2017 at 3:36 PM Michael Martell <mmart...@pivotal.io>
>>>>> wrote:
>>>>> 
>>>>>> Late to this party.
>>>>>> 
>>>>>> Confession 1: I had to look up both RVO and copy-elision.
>>>>>> Confession 2: I don't like using pointers at all. I used to, but I've
>>>>>> evolved to just use C# and Java :)
>>>>>> 
>>>>>> Without investing a lot more time, I don't have strong feelings about
>>>> raw
>>>>>> vs shared pointers. My only question is: Can we return ptr to abstract
>>>>>> class everywhere we return objects? Just thinking of mocking, which
>>>> always
>>>>>> wants to mock interfaces.
>>>>>> 
>>>>>> On Thu, Sep 14, 2017 at 2:25 PM, Michael William Dodge <
>>>> mdo...@pivotal.io
>>>>>>> 
>>>>>> wrote:
>>>>>> 
>>>>>>> +0 shared pointer
>>>>>>> 
>>>>>>>> On 14 Sep, 2017, at 14:09, Ernest Burghardt <eburgha...@pivotal.io>
>>>>>>> wrote:
>>>>>>>> 
>>>>>>>> Calling a vote for:
>>>>>>>> 
>>>>>>>> - Raw pointer
>>>>>>>> - shard pointer
>>>>>>>> 
>>>>>>>> +1 raw Pointer, I had to look up RVO and am new to std::move(s)
>>>>>>>> 
>>>>>>>> On Thu, Sep 14, 2017 at 3:02 PM, Michael William Dodge <
>>>>>>> mdo...@pivotal.io>
>>>>>>>> wrote:
>>>>>>>> 
>>>>>>>>> I generally dig reference-counted pointers for avoiding lifetime
>>>>>> issues
>>>>>>>>> with objects allocated off the heap but I can live with bare
>>>>>> pointers,
>>>>>>> too.
>>>>>>>>> 
>>>>>>>>> Sarge
>>>>>>>>> 
>>>>>>>>>> On 13 Sep, 2017, at 16:25, Mark Hanson <mhan...@pivotal.io>
>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>> Hi All,
>>>>>>>>>> 
>>>>>>>>>> I favor the “pointer" approach that is identified in the code
>>>>>> sample.
>>>>>>>>> There is greater clarity and less bytes seemingly created and
>>>>>> written.
>>>>>>> We
>>>>>>>>> do sacrifice the potential ease of using an object, but in all, I
>>>>>> think
>>>>>>> the
>>>>>>>>> way our code is structured. It is not conducive to do a value
>>>>>> approach,
>>>>>>>>> from an efficiency standpoint,  because of our use of the pimpl
>>>>>> model.
>>>>>>>>>> 
>>>>>>>>>> Thanks,
>>>>>>>>>> Mark
>>>>>>>>>> 
>>>>>>>>>>> On Sep 12, 2017, at 11:09 AM, Jacob Barrett <jbarr...@pivotal.io
>>>>> 
>>>>>>>>> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> My biggest concern with this model is that access to the public
>>>>>> Cache
>>>>>>>>>>> object from other public objects results in additional
>>>> allocations
>>>>>> of
>>>>>>> a
>>>>>>>>>>> Cache value. Think about when we are inside a Serializable object
>>>>>> and
>>>>>>> we
>>>>>>>>>>> access the Cache from DataOutput.
>>>>>>>>>>> 
>>>>>>>>>>> As value:
>>>>>>>>>>> Serializable* MyClass::fromData(DataInput& dataInput) {
>>>>>>>>>>> auto cache = dataOutput.getCache();
>>>>>>>>>>> ...
>>>>>>>>>>> }
>>>>>>>>>>> In this the value of cache will RVO the allocation of Cache in
>>>> the
>>>>>>>>> getCache
>>>>>>>>>>> call into the stack of this method, great. The problem is that
>>>>>> Cache
>>>>>>>>> must
>>>>>>>>>>> contain a std::shared_ptr<CacheImpl> which means that each
>>>>>> allocation
>>>>>>>>> is 8
>>>>>>>>>>> bytes (pointer to control block and pointer to CacheImpl) as well
>>>>>> as
>>>>>>>>> having
>>>>>>>>>>> to increment the strong counter in the control block. On
>>>>>> exit/descope,
>>>>>>>>> the
>>>>>>>>>>> Cache will have to decrement the control block as well.
>>>>>>>>>>> 
>>>>>>>>>>> Using current shared_ptr pimple model:
>>>>>>>>>>> Serializable* MyClass::fromData(DataInput& dataInput) {
>>>>>>>>>>> auto& cache = dataOutput.getCache();
>>>>>>>>>>> ...
>>>>>>>>>>> }
>>>>>>>>>>> We only suffer the ref allocation of 4 bytes and no ref count.
>>>>>> Since
>>>>>>>>> this
>>>>>>>>>>> function call can't survive past the lifespan of Cache/CacheImpl
>>>>>> they
>>>>>>>>> don't
>>>>>>>>>>> need to have shared_ptr and refcounting.
>>>>>>>>>>> 
>>>>>>>>>>> Given that this method could be called numerous times is the
>>>>>> overhead
>>>>>>> of
>>>>>>>>>>> the value version going to be a significant performance issue?
>>>>>>>>>>> 
>>>>>>>>>>> I worry that moves and RVO is just beyond most developers. Heck I
>>>>>>> didn't
>>>>>>>>>>> know anything about it until we started exploring it.
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> -Jake
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> On Tue, Sep 12, 2017 at 8:06 AM David Kimura <dkim...@pivotal.io
>>>>> 
>>>>>>>>> wrote:
>>>>>>>>>>> 
>>>>>>>>>>>> Follow up of attached discussion after more investigation.  I
>>>>>> created
>>>>>>>>> an
>>>>>>>>>>>> example of returning Cache as shared pointer versus raw value:
>>>>>>>>>>>> 
>>>>>>>>>>>> https://github.com/dgkimura/geode-native-sandbox
>>>>>>>>>>>> 
>>>>>>>>>>>> I still like returning by value as it lets the user do what they
>>>>>> want
>>>>>>>>> with
>>>>>>>>>>>> their object.
>>>>>>>>>>>> 
>>>>>>>>>>>> // Here user creates object on their stack.
>>>>>>>>>>>> auto c = CacheFactory::createFactory().create();
>>>>>>>>>>>> 
>>>>>>>>>>>> // Here user creates smart pointer in their heap.
>>>>>>>>>>>> auto cptr =
>>>>>>>>>>>> std::make_shared<Cache>(CacheFactory::createFactory().
>>>> create());
>>>>>>>>>>>> 
>>>>>>>>>>>> Difficulty of implementing this is high due to circular
>>>>>> dependencies
>>>>>>> of
>>>>>>>>>>>> Cache/CacheImpl as well as objects hanging off CacheImpl that
>>>>>> return
>>>>>>>>>>>> Cache.  We must be extra careful when dealing with move/copy
>>>>>>> semantics
>>>>>>>>> of
>>>>>>>>>>>> Cache/CacheImpl.
>>>>>>>>>>>> 
>>>>>>>>>>>> Alternative, is to keep as is and only permit heap allocations
>>>>>> from
>>>>>>>>>>>> factory using shared pointers.
>>>>>>>>>>>> 
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>> David
>>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>> 
>> 

Reply via email to