On 02 Dec 2013, at 21:36, Alex Rousskov <rouss...@measurement-factory.com> 
wrote:

> On 12/02/2013 11:34 AM, Kinkie wrote:
> 
>> +    SBuf operator() (SBuf accumulated, const SBuf &item) {
>> +        if (first) {
>> +            first = false;
>> +            accumulated.append(item);
>> +            return accumulated;
>> +        }
>> +        accumulated.append(separator_).append(item);
>> +        return accumulated;
>> +    }
> 
>> +    SBuf rv;
>> +    rv.reserveSpace(sz);
>> +    rv = std::accumulate(items.begin(), items.end(), rv, 
>> SBufAddContent(separator));
> 
> 
> The above combination feels wrong. Would not the above result in the
> pre-allocated accumulation buffer (rv) disappearing after the first
> operation, and every consecutive operation allocating a new, bigger buffer?

The only way to be sure is tracing, but it shouldn't, as each append operation 
is at the tail of the backing MemBlob's used portion. After some testing, I can 
confirm that:

Before: SBuf51: id @0x16a4d50mem:0x16a8f00,capacity:16388,size:0,refs:1; , 
offset:0, len:0) : ''
After: SBuf51: id @0x16a4d50mem:0x16a8f00,capacity:16388,size:44,refs:1; , 
offset:0, len:44) : 'The quick brown fox jumped over the lazy dog'

(Before is dumped immediately before the std::accumulate, and after immediately 
after)

> If my suspicion is correct, then I think the solution is to move away
> from std::accumulate for content accumulation. That algorithm is from
> <numerics> so perhaps it was never meant for this kind of in-place
> buffering optimization. We can use std::for_each instead (placing the
> accumulation buffer inside the AddContent function class, just like we
> placed the separator) but perhaps you can find a more appropriate
> algorithm at http://www.cplusplus.com/reference/algorithm/

I thought about that as well; this design however seemed quite clear and 
workable, and I could find no reason not to use it :)

> The first std::accumulate use (to calculate the size) seems OK.
> 
> And yes, I know I used std::accumulate twice in my sketch. This just
> proves that STL is not my strong suit (and illustrates why I hate
> sketching things and effectively ending up taking responsibility for any
> problems).

Are you kidding? This sketch is great IMO, no problems to solve. PLUS I was 
able to learn something :)
Computation cost went down from somewhere between 4*N and 6*N depending on 
implementation to 2*N. I'd call it a win.

>>>> plus a specialized SBufListJoin which is simply an instantiation of
>>>> SBufContainerJoin<SBufList>?
>>> 
>>> What will that specialization do differently? I do not think we need it
>>> but perhaps I am missing something.
>> 
>> As above: just convenience,
> 
> Calling SBufContainerJoin(l, s) is as convenient as calling
> SBufListJoin(l, s), right? I do not see the added convenience here.
> IsMember() adds a little bit of convenience, but SBufListJoin() does not
> seem to do that.

True.
Removing it.

>> +/** convert a wordlist to a SBufList
>> + */
> 
> Using /// would save you one line and would prevent the comment from
> looking so awkward :-)

Done

>> +SBufList wordlistToSbufList(wordlist *);
> 
> This one can be called ToSbufList(). The compiler will know you are
> converting wordlist based on the parameter type. There may be more
> functions like that in the future...

It should actually be called ToSBufList. Corrected.

Please let me know if there's any other questions, or if it's OK to merge now :)

  Thanks!
  Kinkie

Reply via email to