[system][filesystem v3] Question about error_code arguments

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >

[system][filesystem v3] Question about error_code arguments

by Beman Dawes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

A POSIX sub-group is looking at C++ bindings for POSIX.

They are talking about a filesystem library binding at least loosely
based on Boost.System, Boost.Filesystem, and C++ TR2.

In looking at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2838.html,
"Library Support for Hybrid Error Handling (Rev 2)", they are
concerned about specifying hybrid error handling like this:

     void f(error_code& ec=throws());

They would rather see it specified like this:

     void f(error_code* ec=0);

One particular concern is that as currently worded, the N2838 proposal
requires throws() return a null reference, which they see as relying
on undefined behavior. I wasn't at the meeting where the LWG asked
that a null reference be mandated; my reading of the standard is that
it is unclear if returning a null reference is or isn't undefined
behavior. Some of the core folks seem to think it is undefined, but
compilers accept it.

Although the reference form is usual for C++, the use of anything
other than the default is limited, and usually in low-level code at
that. Although I could personally live with either form, I'm leaning
slightly toward the pointer form.

Regardless, I'd like to hear Boosters views on the two interfaces
above. Which do you prefer? Why?

--Beman
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Peter Dimov-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Beman Dawes wrote:

> A POSIX sub-group is looking at C++ bindings for POSIX.
>
> They are talking about a filesystem library binding at least loosely
> based on Boost.System, Boost.Filesystem, and C++ TR2.
>
> In looking at
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2838.html,
> "Library Support for Hybrid Error Handling (Rev 2)", they are
> concerned about specifying hybrid error handling like this:
>
>     void f(error_code& ec=throws());
>
> They would rather see it specified like this:
>
>     void f(error_code* ec=0);

...

> Regardless, I'd like to hear Boosters views on the two interfaces
> above. Which do you prefer? Why?

I prefer the pointer form, because it's idiomatic. The reference form is an
invention.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Frank Mori Hess :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tuesday 20 October 2009, Peter Dimov wrote:

> Beman Dawes wrote:
> > A POSIX sub-group is looking at C++ bindings for POSIX.
> >
> > They are talking about a filesystem library binding at least loosely
> > based on Boost.System, Boost.Filesystem, and C++ TR2.
> >
> > In looking at
> > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2838.html,
> > "Library Support for Hybrid Error Handling (Rev 2)", they are
> > concerned about specifying hybrid error handling like this:
> >
> >     void f(error_code& ec=throws());
> >
> > They would rather see it specified like this:
> >
> >     void f(error_code* ec=0);
>
> ...
>
> > Regardless, I'd like to hear Boosters views on the two interfaces
> > above. Which do you prefer? Why?
>
> I prefer the pointer form, because it's idiomatic. The reference form is an
> invention.

I agree.  I've never heard of a null reference in C++ before reading the
original post.  I thought one of the selling points of references was they
can't be null.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkrd3LMACgkQ5vihyNWuA4UnPwCg1fbhc/bdPgUuANv+S3uW4n10
H/IAn1sMfUgjMtA5UYlBnbb3iYjjbQ6Q
=vtTB
-----END PGP SIGNATURE-----
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Thomas Klimpel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Beman Dawes wrote:

> One particular concern is that as currently worded, the N2838 proposal
> requires throws() return a null reference, which they see as relying
> on undefined behavior.
> ...
>
> Although I could personally live with either form, I'm leaning
> slightly toward the pointer form.
>
> Regardless, I'd like to hear Boosters views on the two interfaces
> above. Which do you prefer? Why?

I don't know the details, but I also would prefer the pointer interface. "null reference" reminds me of somebody actually checking against a null reference:

void f(int& r) {
  if (&r) // check whether r is a null reference
    ... ;
  g(&r);
}

I have no problem if "r" could be undefined, i.e. somebody called "f(*p);" with a "p" that is null or undefined. I also don't have a problem if "g" checks the pointer it is passed in against null. However, if "f" itself checks its argument against being a null reference, then I'm disappointed. As another poster said: "I thought one of the selling points of references was they can't be null."


I could probably live with returning an "undefined reference", and if somebody prefers this "undefined reference" to actually be a null reference to simplify debugging, why not. But as soon as he explicitly checks the reference against actually being a null reference, I think he is doing something wrong.


Regards,
Thomas
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Michael Caisse-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thomas Klimpel wrote:

> Beman Dawes wrote:
>  
>> One particular concern is that as currently worded, the N2838 proposal
>> requires throws() return a null reference, which they see as relying
>> on undefined behavior.
>> ...
>>
>> Although I could personally live with either form, I'm leaning
>> slightly toward the pointer form.
>>
>> Regardless, I'd like to hear Boosters views on the two interfaces
>> above. Which do you prefer? Why?
>>    
>
> I don't know the details, but I also would prefer the pointer interface. "null reference" reminds me of somebody actually checking against a null reference:
>
> void f(int& r) {
>   if (&r) // check whether r is a null reference
>     ... ;
>   g(&r);
> }
>
> I have no problem if "r" could be undefined, i.e. somebody called "f(*p);" with a "p" that is null or undefined. I also don't have a problem if "g" checks the pointer it is passed in against null. However, if "f" itself checks its argument against being a null reference, then I'm disappointed. As another poster said: "I thought one of the selling points of references was they can't be null."
>
>  

My exact thoughts.

michael

--

----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Scott McMurray-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/10/20 Beman Dawes <bdawes@...>:
>
> Regardless, I'd like to hear Boosters views on the two interfaces
> above. Which do you prefer? Why?
>

Since it's neither polymorphic nor ownership-transferring, I really
dislike the pointer version.

Now, I have no idea how error_code is specified, but I thought it
would have been something like this, which wouldn't require null
references:

struct error_code {
    static const int throw_instead = ~0;
    error_code(int c = 0) : code_(c) {}
    int code() const { return code_; }
    error_code &operator=(int c) {
        if (code_ == throw_instead) throw system_exception(c);
        code_ = c;
        return *this;
    }
  private:
    int code_;
};

error_code throws_object(error_code::throw_instead);
error_code &throws() { return throws_object; }

That said, I'd much prefer the pointer version to anything that
requires that implementation code check whether the address of a
reference is null, despite my distaste at having to pass &error all
over the place.

~ Scott
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Andrey Semashev-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Scott McMurray wrote:

> 2009/10/20 Beman Dawes <bdawes@...>:
>> Regardless, I'd like to hear Boosters views on the two interfaces
>> above. Which do you prefer? Why?
>>
>
> Since it's neither polymorphic nor ownership-transferring, I really
> dislike the pointer version.
>
> Now, I have no idea how error_code is specified, but I thought it
> would have been something like this, which wouldn't require null
> references:
>
> struct error_code {
>     static const int throw_instead = ~0;
>     error_code(int c = 0) : code_(c) {}
>     int code() const { return code_; }
>     error_code &operator=(int c) {
>         if (code_ == throw_instead) throw system_exception(c);
>         code_ = c;
>         return *this;
>     }
>   private:
>     int code_;
> };
>
> error_code throws_object(error_code::throw_instead);
> error_code &throws() { return throws_object; }
>
> That said, I'd much prefer the pointer version to anything that
> requires that implementation code check whether the address of a
> reference is null, despite my distaste at having to pass &error all
> over the place.

+1, null references are a really weird idea, IMHO. We should not
introduce such precedent in the language support library, especially
since there is an alternative solution that achieves the same result in
a natural way.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Beman Dawes wrote:
>
> They are talking about a filesystem library binding at least loosely
> based on Boost.System, Boost.Filesystem, and C++ TR2.

Good!

> In looking at
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2838.html,
> "Library Support for Hybrid Error Handling (Rev 2)", they are
> concerned about specifying hybrid error handling like this:
>
>      void f(error_code& ec=throws());

When avoiding exceptions, that leads to this code:

   error_code error;
   f(error);

> They would rather see it specified like this:
>
>      void f(error_code* ec=0);

   error_code error;
   f(&error);

As Scott McMurray noted, the call doesn't transfer ownership and isn't polymorphic.  However, using a null pointer to indicate the absence of something is idiomatic as Peter Dimov noted.  From a purely esthetic point of view, I prefer not having to take the address of the error_code to call such a function.

> One particular concern is that as currently worded, the N2838 proposal
> requires throws() return a null reference, which they see as relying
> on undefined behavior. I wasn't at the meeting where the LWG asked
> that a null reference be mandated; my reading of the standard is that
> it is unclear if returning a null reference is or isn't undefined
> behavior. Some of the core folks seem to think it is undefined, but
> compilers accept it.

As with others, this makes me very uncomfortable.  I'd prefer that it be worded as an unspecified reference and that dereferencing it would result in undefined behavior.  However, that begs the question: how does the function determine whether to throw an exception.  If throws() returns an error_code instance that throws when the error is set, then there's no need for a null reference.  Unfortunately, that has a performance downside: the function must be called and the temporary must be created or a reference to a global object must be created for all calls that use the default.  A null pointer default must be cheaper.  Given that this scheme will be standardized, it is quite reasonable to think that compiler vendors will apply suitable magic to eliminate the performance downside (auto-generate overloads, for example).

> Although the reference form is usual for C++, the use of anything
> other than the default is limited, and usually in low-level code at
> that. Although I could personally live with either form, I'm leaning
> slightly toward the pointer form.

I have no experience with such functions, so I can't weigh in on the relative use of the default versus providing an error_code.  Given the widening use cases for this approach, I doubt there is a general case one can cite.  (Certainly those coding in environments without exceptions would bias the numbers.)

In summary, I favor the reference interface so long as there is no mention of a null reference, provided compiler vendors think it can be done optimally.  Otherwise, I can live with the pointer interface.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Scott McMurray-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/10/20 Beman Dawes <bdawes@...>:
>
> Regardless, I'd like to hear Boosters views on the two interfaces
> above. Which do you prefer? Why?
>

Could it be spelt like this instead?

    void f(optional<error_code&> ec = {});

So it'd act like a pointer inside the function, but for users it'd
look like passing a normal reference?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Andrey Semashev-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Stewart, Robert wrote:

> Beman Dawes wrote:
>
>> One particular concern is that as currently worded, the N2838
>> proposal requires throws() return a null reference, which they see
>> as relying on undefined behavior. I wasn't at the meeting where the
>> LWG asked that a null reference be mandated; my reading of the
>> standard is that it is unclear if returning a null reference is or
>> isn't undefined behavior. Some of the core folks seem to think it
>> is undefined, but compilers accept it.
>
> As with others, this makes me very uncomfortable.  I'd prefer that it
> be worded as an unspecified reference and that dereferencing it would
> result in undefined behavior.  However, that begs the question: how
> does the function determine whether to throw an exception.  If
> throws() returns an error_code instance that throws when the error is
> set, then there's no need for a null reference.  Unfortunately, that
> has a performance downside: the function must be called and the
> temporary must be created or a reference to a global object must be
> created for all calls that use the default.  A null pointer default
> must be cheaper.

I think the performance cost of checking a reference or pointer for
validity and checking some property in the error_code instance will be
the same. After all, in both cases it comes down to a single comparison
of two integers. Even if referencing the global default instance does
add overhead, I bet it is negligible.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by OvermindDL1 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Oct 20, 2009 at 12:56 PM, Andrey Semashev
<andrey.semashev@...> wrote:

> Stewart, Robert wrote:
>>
>> Beman Dawes wrote:
>>
>>> One particular concern is that as currently worded, the N2838
>>> proposal requires throws() return a null reference, which they see
>>> as relying on undefined behavior. I wasn't at the meeting where the
>>> LWG asked that a null reference be mandated; my reading of the
>>> standard is that it is unclear if returning a null reference is or
>>> isn't undefined behavior. Some of the core folks seem to think it
>>> is undefined, but compilers accept it.
>>
>> As with others, this makes me very uncomfortable.  I'd prefer that it
>> be worded as an unspecified reference and that dereferencing it would
>> result in undefined behavior.  However, that begs the question: how
>> does the function determine whether to throw an exception.  If
>> throws() returns an error_code instance that throws when the error is
>> set, then there's no need for a null reference.  Unfortunately, that
>> has a performance downside: the function must be called and the
>> temporary must be created or a reference to a global object must be
>> created for all calls that use the default.  A null pointer default
>> must be cheaper.
>
> I think the performance cost of checking a reference or pointer for validity
> and checking some property in the error_code instance will be the same.
> After all, in both cases it comes down to a single comparison of two
> integers. Even if referencing the global default instance does add overhead,
> I bet it is negligible.

I prefer a references interface from ease of use, however it should
never have a null pointer.  Why not have two functions of the same
name, one takes a reference, the other a pointer, thus you can handle
both cases and enforced that the reference cannot be null.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andrey Semashev wrote:

> Stewart, Robert wrote:
> > Beman Dawes wrote:
> >
> > set, then there's no need for a null reference.  Unfortunately, that
> > has a performance downside: the function must be called and the
> > temporary must be created or a reference to a global object must be
> > created for all calls that use the default.  A null pointer default
> > must be cheaper.
>
> I think the performance cost of checking a reference or pointer for
> validity and checking some property in the error_code
> instance will be
> the same. After all, in both cases it comes down to a single
> comparison
> of two integers. Even if referencing the global default instance does
> add overhead, I bet it is negligible.

I wasn't referring to checking the reference or pointer.  Rather, I was pointing out that the reference must be bound to something when the default is accepted.  Every call using the default implies code that acquires an object or reference to one to which the formal parameter can be bound.  That is costlier than simply passing a null pointer unless some compiler magic is involved.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

OvermindDL1 wrote:
> > Stewart, Robert wrote:
> >> Beman Dawes wrote:
> >>
> >>> One particular concern is that as currently worded, the N2838
> >>> proposal requires throws() return a null reference, which they see
[snip]
>
> Why not have two functions of the same
> name, one takes a reference, the other a pointer, thus you can handle
> both cases and enforced that the reference cannot be null.

If you read the referenced proposal, you'll note that the idea was to avoid exploding interfaces to account for all functions using this error handling approach.  That is, for every such function, there must be an additional overload, whereas a single overload suffices with the proposed design.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Detlef Vollmann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andrey Semashev wrote:
> I think the performance cost of checking a reference or pointer for
> validity and checking some property in the error_code instance will be
> the same. After all, in both cases it comes down to a single comparison
> of two integers. Even if referencing the global default instance does
> add overhead, I bet it is negligible.
No, it isn't.  The null pointer will be in a register, while the
global object might not even be in the cache.
And this for functions that are called by the thousands per second
on a busy server.

   Detlef

PS: This was one of the main reasons why the POSIX/C++ group is
in favour of the pointer.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Detlef Vollmann wrote:

> Andrey Semashev wrote:
>> I think the performance cost of checking a reference or pointer for
>> validity and checking some property in the error_code instance will
>> be the same. After all, in both cases it comes down to a single
>> comparison of two integers. Even if referencing the global default
>> instance does add overhead, I bet it is negligible.
> No, it isn't.  The null pointer will be in a register, while the
> global object might not even be in the cache.
> And this for functions that are called by the thousands per second
> on a busy server.
>
>   Detlef
>
> PS: This was one of the main reasons why the POSIX/C++ group is
> in favour of the pointer.

Why does the global object need to be read?

static error_code throws_;

error_code& throws() { return(throws_); }

void f(error_code& ec = throws()) {
    if(&ec == &throws()) {
        throw ...;
    } else {
        ....
    }
}

This should not actually load anything except the address of
the global error_code.  The only advantage of using a null pointer
is that it can be checked with a slightly simpler instruction.

In Christ,
Steven Watanabe

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Detlef Vollmann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Steven Watanabe wrote:
> Detlef Vollmann wrote:
>> Andrey Semashev wrote:
>>> I think the performance cost of checking a reference or pointer for
>>> validity and checking some property in the error_code instance will
>>> be the same. After all, in both cases it comes down to a single
>>> comparison of two integers. Even if referencing the global default
>>> instance does add overhead, I bet it is negligible.
>> No, it isn't.  The null pointer will be in a register, while the
>> global object might not even be in the cache.

> Why does the global object need to be read?
>
> static error_code throws_;
>
> error_code& throws() { return(throws_); }
>
> void f(error_code& ec = throws()) {
>    if(&ec == &throws()) {
>        throw ...;
>    } else {
>        ....
>    }
> }
>
> This should not actually load anything except the address of
> the global error_code.
Loading the address from the symbol table also takes time.
With a clever linker the cost might be very small, but if you look
how many functions might get such signatures, and how often these
functions are called, it's not negligible.
It might be negligible on a CISC machine, but we don't only deal
with CISC machines.

   Detlef

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Christopher Kohlhoff :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I will reluctantly drag my brain out of holiday mode to put in my 2c
here :)

On Tue, 20 Oct 2009 11:15 -0400, "Beman Dawes" <bdawes@...> wrote:

> A POSIX sub-group is looking at C++ bindings for POSIX.
>
> They are talking about a filesystem library binding at least loosely
> based on Boost.System, Boost.Filesystem, and C++ TR2.
>
> In looking at
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2838.html,
> "Library Support for Hybrid Error Handling (Rev 2)", they are
> concerned about specifying hybrid error handling like this:
>
>      void f(error_code& ec=throws());
>
> They would rather see it specified like this:
>
>      void f(error_code* ec=0);
[...]

> Although the reference form is usual for C++, the use of anything
> other than the default is limited, and usually in low-level code at
> that.

As background to my point of view, I would say that this experience is
not true for Asio users. The use of the non-defaulted call (or rather,
its equivalent in Asio) is not limited, but widespread.

Where applicable, Asio provides overloads:

  void f();
  error_code f(error_code& ec);

The throwing overloads are most typically in small programs or at
program startup. Non-trivial programs will tend towards the second,
non-throwing overload. It is the nature of network applications to
react to errors as part of normal control flow, and exception handling
is not a good approach for that.

> Regardless, I'd like to hear Boosters views on the two interfaces
> above. Which do you prefer? Why?

First, allow me to register my strong dislike for the pointer form. In
fact, I am not in favour of any specification that disallows the
existence of two separate overloads: throwing and non-throwing.

This:

  void f(error_code* ec = 0);

supports both throwing and non-throwing modes. From the compiler's
point of view, any calling code must also support exceptions and so a
space and/or time cost is paid for unwinding, even if it is not
required.

A two-overload approach lets a library do something like:

  void f();
  void f(error_code& ec) [[nothrow]];

In user code that calls the second form pays no cost for exception
handling, and the compiler may do more static analysis and
optimisation based on the nothrow attribute. It seems a bit odd to be
quibbling over the cost of comparing pointers when some costs of
exception handling are forced on everybody.

Second, I do not pay the "explosion" of overloads argument. (Yes,
there is a doubling.) The potential "explosion" comes from a throwing
operation with defaulted arguments:

  void f(int a, int b = 0, int c = 0);

where ideally the user would like to see the following non-throwing
variants:

  void f(int a, error_code& ec);
  void f(int a, int b, error_code& ec);
  void f(int a, int b, int c, error_code& ec);

However the proposed pointer form would be

  void f(int a, int b = 0, int c = 0, error_code* ec = 0);

And so a user must specify all arguments to use the non-throwing form.
If you're happy to require users to do so, then the only non-throwing
reference-based overload required is:

  void f(int a, int b, int c, error_code& ec);

I have had some Asio users complain that I have left out some
non-throwing overloads. They now have to be aware of the default
arguments where otherwise they could have ignored them. Therefore, the
"explosion" is a cost that can be paid by a library to improve
usability, but it is not inherent in the overload approach.

However, it's true there is a doubling of overloads. In my opinion it
is a cost worth paying (in specification and implementation) to allow
users to avoid the costs of exception handling. In my experience, it's
not *that* big a cost anyway. So as I said, I'm not in favour of a
specification that excludes that approach.

If there was to be a change to the throwing/non-throwing error_code
idiom, then what I would suggest is putting the error_code parameter
*first*. For example:

  void f(int a, int b = 0, int c = 0);
  void f(error_code& ec, int a, int b = 0, int c = 0);

This avoids the explosion issue due to defaulted arguments, although
you still get doubling. What's especially nice is that it should work
with C++0x variadic templates, while the other approaches do not
AFAIK.

Cheers,
Chris
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Andrey Semashev-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Stewart, Robert wrote:

> Andrey Semashev wrote:
>> Stewart, Robert wrote:
>>> Beman Dawes wrote:
>>>
>>> set, then there's no need for a null reference.  Unfortunately,
>>> that has a performance downside: the function must be called and
>>> the temporary must be created or a reference to a global object
>>> must be created for all calls that use the default.  A null
>>> pointer default must be cheaper.
>> I think the performance cost of checking a reference or pointer for
>>  validity and checking some property in the error_code instance
>> will be the same. After all, in both cases it comes down to a
>> single comparison of two integers. Even if referencing the global
>> default instance does add overhead, I bet it is negligible.
>
> I wasn't referring to checking the reference or pointer.  Rather, I
> was pointing out that the reference must be bound to something when
> the default is accepted.  Every call using the default implies code
> that acquires an object or reference to one to which the formal
> parameter can be bound.  That is costlier than simply passing a null
> pointer unless some compiler magic is involved.

The call to throws() can be inlined so that the global object
acquisition turns into loading its address in a register. The address is
known at compile time, so there's little difference between loading a
zero into a pointer/reference argument and loading a valid address into
a reference argument. No magic needed for this to happen.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Andrey Semashev-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Detlef Vollmann wrote:

> Andrey Semashev wrote:
>> I think the performance cost of checking a reference or pointer for
>> validity and checking some property in the error_code instance will be
>> the same. After all, in both cases it comes down to a single
>> comparison of two integers. Even if referencing the global default
>> instance does add overhead, I bet it is negligible.
> No, it isn't.  The null pointer will be in a register, while the
> global object might not even be in the cache.
> And this for functions that are called by the thousands per second
> on a busy server.
>
> PS: This was one of the main reasons why the POSIX/C++ group is
> in favour of the pointer.

If the global object is used so often, it will likely be in cache. If
not often, it doesn't matter. An whether the compiler can load a
structure of size equal to int into a register is a question of the
compiler's prosperity.

Anyway, I'd prefer code clarity in this case instead of a possible tiny
performance gain that will be swallowed by the surrounding code.
Consider it in comparison with a file system operation cost, for example.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [system][filesystem v3] Question about error_code arguments

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andrey Semashev wrote:

> Stewart, Robert wrote:
> >>>
> > I wasn't referring to checking the reference or pointer.  Rather, I
> > was pointing out that the reference must be bound to something when
> > the default is accepted.  Every call using the default implies code
> > that acquires an object or reference to one to which the formal
> > parameter can be bound.  That is costlier than simply passing a null
> > pointer unless some compiler magic is involved.
>
> The call to throws() can be inlined so that the global object
> acquisition turns into loading its address in a register. The
> address is
> known at compile time, so there's little difference between loading a
> zero into a pointer/reference argument and loading a valid
> address into
> a reference argument. No magic needed for this to happen.

If the global object is created before all code calling throws() is done, then its address can be taken safely by multiple threads.  Doing so requires compiler/runtime magic.

If the global object is created each time, there's code to create that object for each call accepting the default.  I'm not speculating whether that construction is trivial, so there is, at least potentially, a cost per call accepting the default in such a case.

Finally, the zero for a null pointer default can be coded close to the call or even embedded in an instruction.  Fetching the address of a global object cannot so optimized, so every call accepting the default incurs a greater cost.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >