Boost logo

Boost :

Subject: Re: [boost] [xint] Boost.XInt formal review
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2011-03-05 22:15:02


On 3/5/2011 5:55 PM, Chad Nelson wrote:
> On Sat, 05 Mar 2011 13:41:16 -0800
> "Jeffrey Lee Hellrung, Jr."<jhellrung_at_[hidden]> wrote:
[...]
>> Regarding the former, it appears we still don't have a definitive
>> benchmark comparing COW with move emulation, and one would be nice,
>> but we can still predict how many deep copies each strategy will
>> require for a given expression, and except in constrained situations
>> where copies are never modified, I don't think COW gives any benefit.
>> Sometimes COW is worse, since you can't explicitly transfer
>> ownership. Feel free to prove me wrong. [...]
>
> I'll be sure to report the results, either way.

Looking forward to it. It would also help to track the number of
allocations via the allocator or defining global new to ensure we get
the allocation statistics one expects.

[...]
>> For what it's worth, I will vote to not accept, but I will try to
>> summarize my reasons for doing so in a separate email.
>
> In any case, thank you for your comments. I'm a little puzzled why you
> would vote to reject it though, instead of a conditional acceptance.
> You seem to have clear conditions you want resolved.

Yes, however, in a nutshell, I feel there is too much on the "TODO" list
that it precludes a full endorsement at present. I'm only one person,
though.

[...]
>> I think a quick trip to wikipedia, as suggested by Robert, should
>> convince you.
>
> That was one of the sources of my informal knowledge on the subject, and
> at least the last time I looked, it explained nothing that I could see
> about why O(n/2) == O(n).

Right there in the definition:

http://en.wikipedia.org/wiki/Big_oh#Formal_definition

To paraphrase:

f(x) = O(g(x)) as x -> inf

iff there exists an M and x0 s.t.

|f(x)| <= M * |g(x)| for all x > x0

So n = O(k*n) for any constant k (say, 1/2, or 2) simply by setting M in
the above to k.

Basically, multiplicative constants don't matter as far as complexity is
concern, and neither do lower order additive terms. Informally, what
complexity estimates tell you is the relative growth in the running time
of an algorithm as you increase the problem size.

[...]
>> Sorry if this wasn't clear, so let me rephrase. Which implementation
>> function or block of code necessitates using COW to eliminate
>> unnecessary copying? This doesn't require benchmarking, only code
>> analysis.
>
> I don't have that information at present. I'll certainly let you know
> if I discover specific places.

To aid in your discovery, find any algorithm you're currently using that
takes advantage of COW, and remove the "attach" and "detach" and similar
COW operations and (roughly) replace them with copy and/or move
operations. If you can't do that without invoking an unnecessary
allocation, let me know.

>>>>> I had a publicly-available make_unique function in an earlier
>>>>> iteration of the library, and was criticized for it, so I removed
>>>>> it. I don't remember if it was you personally doing the
>>>>> criticizing, but you-the-Boost-community can't have it both
>>>>> ways. :-)
>>>>
>>>> Well this tagged copy constructor pretty much amounts to the same
>>>> thing, doesn't it? Only less efficient, since it will actually
>>>> perform a deep copy in situations where it's not needed, e.g., when
>>>> the object is already in the thread you want it to be owned in.
>>>
>>> Only if the person is foolish enough to explicitly tell the library
>>> to do so. I'd like to think that any programmer using the library
>>> wouldn't be that foolish.
>>
>> You didn't really address my primary comment. You can put lipstick on
>> a pig, but it's still a pig. You've just renamed make_unique into a
>> constructor. Is that a fair analysis?
>
> Yes. The complaint, as I recall, wasn't that the make_unique function
> existed, but that it was part of the interface and meant to be used or
> at least usable by client code. I didn't understand it either.

So you didn't really faithfully address the complaint. The interface
still has the make_unique functionality; you just put lipstick on it ;)
  More importantly though...

You (or anyone else!) don't necessarily have to accept anyone's or
everyone's suggestion. If you feel like you have a compelling case to
reject a particular request or do things a certain way, make your case,
and your case and the opposing one(s) will be evaluated on its merits.
Initially, I, too, may have thought the make_unique member function
exposed too much of the implementation, but it makes sense to provide in
the event that you want to force an object to have sole ownership of its
data for thread safety purposes. For contentious features, some kind of
justification or rationale in the documentation can go a long way.

>>>> And more cryptic in client code. By the way, is there ever any
>>>> reason to set the boolean force_thread_safety to false?
>>>
>>> It should essentially *always* be false, that's why false is the
>>> default value. [...]
>>
>> Sorry, is there any reason to set the boolean force_thread_safety
>> *explicitly* to false? I suspect the answer is "no", so I would
>> consider this an inferior design [...]
>
> Duplicating the code of that constructor function, with what I think
> would be a single-line change, would be a superior design? I'm not
> trying to be a pain, I'm honestly baffled at that assertion.

In the interest of list traffic, I'm going to drop this line of
discussion, if you don't mind. It's not important enough to belabor (sp?).

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk