[system] Would it be possible to trial a breaking change to Boost.System and see what happens?

classic Classic list List threaded Threaded
78 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

[system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
SG14 the low latency study has been looking into how to improve some
design decisions in <system_error>. The relevant WG21 paper is
https://wg21.link/P0824 and recent discussion can be found at
https://groups.google.com/a/isocpp.org/forum/#!topic/sg14/j7tQybEjP5s.

What we'd like to do is to test whether some very mildly breaking
changes to <system_error> are so mild as to affect no users, and on that
basis propose WG21 to make those mildly breaking changes to
<system_error> in the next C++ standard. And to test this, we'd like to
modify Boost.System with those mildly breaking changes, ship a release
and see how many users complain. If it is zero, we have evidence for
WG21 that this is not a consequential change.

What we'd like to change is this:

1. Stop treating code zero as always meaning success irrespective of
category. This remedies a defect where some custom error code domains
cannot be represented by error_code due to using value 0 for an error.
In actual code, I've never seen anyone ever use comparison to anything
but a default constructed error code, so I think this will be safe.

2. Success becomes solely the default constructed error code, which is
code zero and a new category of "null_category". This is internally
represented by { 0, nullptr }, and thus makes the default constructor
trivial which is highly desirable as it eliminates any compiler magic
static fencing for the default constructor. Right now the default
constructor uses system_category with value 0, and I suspect no code
will notice this change either.

3, Make the default constructor constexpr, now possible. No code should
notice a difference, except less runtime code will be generated.

4. error_code::message() returns a std::string_view instead of
std::string if running C++ 17 or better. This lets us remove the
<string> dependency, and thus stop dragging in half the STL with
<system_error> which in turn makes <system_error> actually useful to the
embedded systems crowd. The guess here is that std::string_view has such
excellent interoperation with std::string that I think 99% of code will
compile and work perfectly without anybody noticing a thing.


I appreciate that this would undo Peter Dimov's excellent work at having
Boost.System alias <system_error> under C++ 11 and later. I also
appreciate that we are deliberately going to potentially break end user
code. But my personal guess is that in practice, the breakage will not
be noticed by 99% of code out there right now. It'll just compile
against the improved Boost.System and everything will work as before.

Boost was originally intended as an incubator for C++ standard changes.
This ticks that box perfectly.

Thoughts on feasibility?

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
Niall Douglas wrote:

> 3, Make the default constructor constexpr, now possible.

See https://cplusplus.github.io/LWG/issue2992

Although the solution you propose is worth looking into in either case.

> 4. error_code::message() returns a std::string_view

How do you envisage this being implemented? A string_view into what?

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 01/12/18 20:43, Niall Douglas via Boost wrote:

> SG14 the low latency study has been looking into how to improve some
> design decisions in <system_error>. The relevant WG21 paper is
> https://wg21.link/P0824 and recent discussion can be found at
> https://groups.google.com/a/isocpp.org/forum/#!topic/sg14/j7tQybEjP5s.
>
> What we'd like to do is to test whether some very mildly breaking
> changes to <system_error> are so mild as to affect no users, and on that
> basis propose WG21 to make those mildly breaking changes to
> <system_error> in the next C++ standard. And to test this, we'd like to
> modify Boost.System with those mildly breaking changes, ship a release
> and see how many users complain. If it is zero, we have evidence for
> WG21 that this is not a consequential change.
>
> What we'd like to change is this:
>
> 1. Stop treating code zero as always meaning success irrespective of
> category. This remedies a defect where some custom error code domains
> cannot be represented by error_code due to using value 0 for an error.
> In actual code, I've never seen anyone ever use comparison to anything
> but a default constructed error code, so I think this will be safe.

In my code I'm using contextual conversion to bool extensively, e.g. "if
(err)" or "if (!err)". This is currently equivalent to comparing against
0, so I assume it will be broken by this change. So, you can count me
right now as the one (loudly) complaining, among many others, I think.

> 2. Success becomes solely the default constructed error code, which is
> code zero and a new category of "null_category". This is internally
> represented by { 0, nullptr }, and thus makes the default constructor
> trivial which is highly desirable as it eliminates any compiler magic
> static fencing for the default constructor. Right now the default
> constructor uses system_category with value 0, and I suspect no code
> will notice this change either.

This breaks "category()" as it returns a reference now. Also,
"message()" has to check for a null category now.

> 3, Make the default constructor constexpr, now possible. No code should
> notice a difference, except less runtime code will be generated.

Not sure there will be any difference in the generated code, since the
constructor still has to initialize the int and the pointer. Optimizers
are already able to propagate constants even if the code is not constexpr.

The real benefit, it seems, is the ability to use error_code in constant
expressions. I'm not sure how useful this is, I've never had a case
where I needed this.

> 4. error_code::message() returns a std::string_view instead of
> std::string if running C++ 17 or better. This lets us remove the
> <string> dependency, and thus stop dragging in half the STL with
> <system_error> which in turn makes <system_error> actually useful to the
> embedded systems crowd. The guess here is that std::string_view has such
> excellent interoperation with std::string that I think 99% of code will
> compile and work perfectly without anybody noticing a thing.

This will only work if "error_category::message()" returns a string from
a static storage. It will not allow relying on strerror_r or similar
API, for example. This will make migration problematic if users define
their own error categories that rely on external API like that.

> I appreciate that this would undo Peter Dimov's excellent work at having
> Boost.System alias <system_error> under C++ 11 and later. I also
> appreciate that we are deliberately going to potentially break end user
> code. But my personal guess is that in practice, the breakage will not
> be noticed by 99% of code out there right now. It'll just compile
> against the improved Boost.System and everything will work as before.
>
> Boost was originally intended as an incubator for C++ standard changes.
> This ticks that box perfectly.
>
> Thoughts on feasibility?

Even besides that my code is likely to be broken by this, I think this
is a really bad idea. Sure, Boost was concieved as the playground for
the features that are potentially later included into the standard, but
it is also a major C++ library that is widely used in the industry.
Breaking users' code willy-nilly does not do any good neither to Boost
nor to its users. So no, no breaking changes to see how bad its smells
afterwards, please.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
Andrey Semashev wrote:

> In my code I'm using contextual conversion to bool extensively, e.g. "if
> (err)" or "if (!err)". This is currently equivalent to comparing against
> 0, so I assume it will be broken by this change.

It will only be broken if you rely on `error_code( 0, some-category )` to
contextually-convert to `false`. A default-constructed error_code, or one
that's been cleared, will still be `false`.

A principled approach would be to ask the category whether a code is `true`
or `false`, but that might be complexity and overhead nobody needs.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
On 01/12/18 21:32, Peter Dimov via Boost wrote:
> Andrey Semashev wrote:
>
>> In my code I'm using contextual conversion to bool extensively, e.g.
>> "if (err)" or "if (!err)". This is currently equivalent to comparing
>> against 0, so I assume it will be broken by this change.
>
> It will only be broken if you rely on `error_code( 0, some-category )`
> to contextually-convert to `false`.

I'm not sure how I can *not* rely on that since I construct `error_code`
from enums or ints, all of them having 0 as the "success" value
precisely to allow the contextual conversion produce the intended result.

> A principled approach would be to ask the category whether a code is
> `true` or `false`, but that might be complexity and overhead nobody needs.

True.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
Andrey Semashev wrote:
> > It will only be broken if you rely on `error_code( 0, some-category )`
> > to contextually-convert to `false`.
>
> I'm not sure how I can *not* rely on that since I construct `error_code`
> from enums or ints, all of them having 0 as the "success" value precisely
> to allow the contextual conversion produce the intended result.

That's exactly what Niall wanted to know, I suppose; would it be possible
for you to give specific examples from your code that would be broken?


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
On 01/12/18 21:46, Peter Dimov via Boost wrote:

> Andrey Semashev wrote:
>> > It will only be broken if you rely on `error_code( 0, some-category
>> )` > to contextually-convert to `false`.
>>
>> I'm not sure how I can *not* rely on that since I construct
>> `error_code` from enums or ints, all of them having 0 as the "success"
>> value precisely to allow the contextual conversion produce the
>> intended result.
>
> That's exactly what Niall wanted to know, I suppose; would it be
> possible for you to give specific examples from your code that would be
> broken?

I suppose, code like this:

   enum class my_errors
   {
     success = 0
   };

   void foo(error_code& err)
   {
     // Do stuff...
     err = make_error_code(success); // error_code(0, my_category)
   }

   void bar()
   {
     error_code err;
     foo(err);
     if (err)
       complain();
   }

I suppose, you could argue that I could avoid `err` initialization in
`foo`, but that is a matter of taste and whether you want to rely on the
initial state of `err` on entry into `foo`. I'm also not happy to have
to convert that initialization to

     err = error_code();

because it loses information about the error category, which may be
useful if I want to print `err` to log even if it is a success.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
Andrey Semashev wrote:
>    void foo(error_code& err)
>    {
>      // Do stuff...
>      err = make_error_code(success); // error_code(0, my_category)
>    }
...
> I suppose, you could argue that I could avoid `err` initialization in
> `foo`, but that is a matter of taste and whether you want to rely on the
> initial state of `err` on entry into `foo`.

No, I'm not going to argue that; it's idiomatic to clear `err` on entry:

void foo( error_code& err )
{
    err.clear();
    // do stuff
}

with the alternative

    err.assign( 0, err.category() );

being used nowadays to avoid the overhead in .clear caused by the "magic
static" Niall talks about.

This latter "idiom" is obviously broken after NIall's suggested change
though.

> I'm also not happy to have to convert that initialization to
>
>      err = error_code();
>
> because it loses information about the error category, which may be useful
> if I want to print `err` to log even if it is a success.

Interesting. You rely on there being different success error_codes? This is
also in direct opposition to the requested change.

How would you suggest we solve the problem of zero being an error in some
contexts?


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
On 01/12/18 22:03, Peter Dimov via Boost wrote:

> Andrey Semashev wrote:
>>    void foo(error_code& err)
>>    {
>>      // Do stuff...
>>      err = make_error_code(success); // error_code(0, my_category)
>>    }
> ...
>> I suppose, you could argue that I could avoid `err` initialization in
>> `foo`, but that is a matter of taste and whether you want to rely on
>> the initial state of `err` on entry into `foo`.
>
> No, I'm not going to argue that; it's idiomatic to clear `err` on entry:
>
> void foo( error_code& err )
> {
>     err.clear();
>     // do stuff
> }
>
> with the alternative
>
>     err.assign( 0, err.category() );
>
> being used nowadays to avoid the overhead in .clear caused by the "magic
> static" Niall talks about.
>
> This latter "idiom" is obviously broken after NIall's suggested change
> though.

I don't think this matches my intent. The `foo` function belongs to the
domain that defines error codes described by the `my_errors` enum and it
is supposed to return one of those codes. Preserving whatever error
category was set in `err` on entry does not achieve that. What I want is
that `err` has `my_category` unconditionally on return from `foo`.

>> I'm also not happy to have to convert that initialization to
>>
>>      err = error_code();
>>
>> because it loses information about the error category, which may be
>> useful if I want to print `err` to log even if it is a success.
>
> Interesting. You rely on there being different success error_codes?

Yes, mostly for diagnostic purposes. Although it may also be a useful
feature to check the domain when comparing two error codes.

> How would you suggest we solve the problem of zero being an error in
> some contexts?

Besides moving the check for the error code into the category? I
suppose, `make_error_code` could perform some kind of mapping onto
another enum that has success value of 0. It can be as simple as this:

   enum foreign_errors
   {
     error = 0,
     success = 1
   };

   enum class internal_errors
   {
     error = -1,
     success = 0
   };

   error_code make_error_code(foreign_errors ec)
   {
     return error_code(ec - 1, my_category);
   }

   error_code make_error_code(internal_errors ec)
   {
     return error_code(ec, my_category);
   }

Another solution would be to make error category have a public member,
which is cheap to access, that would return the "success" value.

   // std::error_category
   class error_category
   {
     int success_value;

   public:
     explicit error_category(int sv = 0) : success_value(sv) {}
     int get_success_value() const noexcept { return success_value; }
   };

   class my_category final :
     public error_category
   {
   public:
     my_category() : error_category(1) {}
   };

   bool error_code::operator bool() const
   {
     return value() != category().get_success_value();
   }

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
Andrey Semashev wrote:

> I don't think this matches my intent. The `foo` function belongs to the
> domain that defines error codes described by the `my_errors` enum and it
> is supposed to return one of those codes. Preserving whatever error
> category was set in `err` on entry does not achieve that. What I want is
> that `err` has `my_category` unconditionally on return from `foo`.

In the general case, foo can call bar, which can also fail and return
whatever error_code it likes. This is analogous to exceptions; mandating
that functions from a specific domain only ever throw exceptions from that
same domain quickly becomes burdensome.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 1/12/2018 12:43 PM, Niall Douglas via Boost wrote:

> SG14 the low latency study has been looking into how to improve some
> design decisions in <system_error>. The relevant WG21 paper is
> https://wg21.link/P0824 and recent discussion can be found at
> https://groups.google.com/a/isocpp.org/forum/#!topic/sg14/j7tQybEjP5s.
>
> What we'd like to do is to test whether some very mildly breaking
> changes to <system_error> are so mild as to affect no users, and on that
> basis propose WG21 to make those mildly breaking changes to
> <system_error> in the next C++ standard. And to test this, we'd like to
> modify Boost.System with those mildly breaking changes, ship a release
> and see how many users complain. If it is zero, we have evidence for
> WG21 that this is not a consequential change.

The usual way is to announce the upcoming change in release nnn and then
make the change in release nnn + 1. What is wrong with using this method
in your case, if all parties are in agreement to do it ?

>
> What we'd like to change is this:
>
> 1. Stop treating code zero as always meaning success irrespective of
> category. This remedies a defect where some custom error code domains
> cannot be represented by error_code due to using value 0 for an error.
> In actual code, I've never seen anyone ever use comparison to anything
> but a default constructed error code, so I think this will be safe.
>
> 2. Success becomes solely the default constructed error code, which is
> code zero and a new category of "null_category". This is internally
> represented by { 0, nullptr }, and thus makes the default constructor
> trivial which is highly desirable as it eliminates any compiler magic
> static fencing for the default constructor. Right now the default
> constructor uses system_category with value 0, and I suspect no code
> will notice this change either.
>
> 3, Make the default constructor constexpr, now possible. No code should
> notice a difference, except less runtime code will be generated.
>
> 4. error_code::message() returns a std::string_view instead of
> std::string if running C++ 17 or better. This lets us remove the
> <string> dependency, and thus stop dragging in half the STL with
> <system_error> which in turn makes <system_error> actually useful to the
> embedded systems crowd. The guess here is that std::string_view has such
> excellent interoperation with std::string that I think 99% of code will
> compile and work perfectly without anybody noticing a thing.
>
>
> I appreciate that this would undo Peter Dimov's excellent work at having
> Boost.System alias <system_error> under C++ 11 and later. I also
> appreciate that we are deliberately going to potentially break end user
> code. But my personal guess is that in practice, the breakage will not
> be noticed by 99% of code out there right now. It'll just compile
> against the improved Boost.System and everything will work as before.
>
> Boost was originally intended as an incubator for C++ standard changes.
> This ticks that box perfectly.
>
> Thoughts on feasibility?
>
> Niall
>



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 01/12/18 23:38, Peter Dimov via Boost wrote:

> Andrey Semashev wrote:
>
>> I don't think this matches my intent. The `foo` function belongs to
>> the domain that defines error codes described by the `my_errors` enum
>> and it is supposed to return one of those codes. Preserving whatever
>> error category was set in `err` on entry does not achieve that. What I
>> want is that `err` has `my_category` unconditionally on return from
>> `foo`.
>
> In the general case, foo can call bar, which can also fail and return
> whatever error_code it likes. This is analogous to exceptions; mandating
> that functions from a specific domain only ever throw exceptions from
> that same domain quickly becomes burdensome.

I wouldn't say so. If I'm writing a library I would make it throw
exceptions that belong to it. If it uses e.g. Boost.Filesystem then in
the parts where it is used Boost.Filesystem can throw its own
exceptions, which may propagate to the user. But in no case would I be
throwing Boost.Filesystem exceptions myself from my library.

It's the same with error codes. The only difference is that we have to
have a success error code as well.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
>> 1. Stop treating code zero as always meaning success irrespective of
>> category. This remedies a defect where some custom error code domains
>> cannot be represented by error_code due to using value 0 for an error.
>> In actual code, I've never seen anyone ever use comparison to anything
>> but a default constructed error code, so I think this will be safe.
>
> In my code I'm using contextual conversion to bool extensively, e.g. "if
> (err)" or "if (!err)". This is currently equivalent to comparing against
> 0, so I assume it will be broken by this change. So, you can count me
> right now as the one (loudly) complaining, among many others, I think.

Sorry, I forgot to mention that the category would be asked whether the
error code's current value is success or failure (its's Friday, and my
current contract is many hours drive from home. Sorry)

This is unavoidable because system_category (on POSIX and Win32) and
generic_category both define value = 0 as success. In some other error
code domain, -1 might mean success. Or 9999. Up to the domain. No
requirement that 0 be set aside as special, as currently.

>> 2. Success becomes solely the default constructed error code, which is
>> code zero and a new category of "null_category". This is internally
>> represented by { 0, nullptr }, and thus makes the default constructor
>> trivial which is highly desirable as it eliminates any compiler magic
>> static fencing for the default constructor. Right now the default
>> constructor uses system_category with value 0, and I suspect no code
>> will notice this change either.
>
> This breaks "category()" as it returns a reference now.

It would still return a reference, just as now. You would check for
internal nullptr, if so return a static null_category.

> Also, "message()" has to check for a null category now.

I don't think that much cost relative to constructing a std::string.

>> 3, Make the default constructor constexpr, now possible. No code should
>> notice a difference, except less runtime code will be generated.
>
> Not sure there will be any difference in the generated code, since the
> constructor still has to initialize the int and the pointer. Optimizers
> are already able to propagate constants even if the code is not constexpr.

But it cannot elide the potential call to an extern function, the
function which retrieves the error_category&. And therefore must emit
code, just in case the system_category might be fetched.

The present design of error_code generates code bloat when used by
Outcome or Expected. Changing it as I describe stops forcing the
compiler to emit code, and thus allows the compiler to fold more code
during optimisation, thus emitting less assembler. Tighter, less bloaty
code is the result.

> The real benefit, it seems, is the ability to use error_code in constant
> expressions. I'm not sure how useful this is, I've never had a case
> where I needed this.

This is not a motivator for me at least. My issue is the side effects on
code bloat. It annoys me when the fix is within easy reach.

>> 4. error_code::message() returns a std::string_view instead of
>> std::string if running C++ 17 or better. This lets us remove the
>> <string> dependency, and thus stop dragging in half the STL with
>> <system_error> which in turn makes <system_error> actually useful to the
>> embedded systems crowd. The guess here is that std::string_view has such
>> excellent interoperation with std::string that I think 99% of code will
>> compile and work perfectly without anybody noticing a thing.
>
> This will only work if "error_category::message()" returns a string from
> a static storage. It will not allow relying on strerror_r or similar
> API, for example. This will make migration problematic if users define
> their own error categories that rely on external API like that.

You are correct that the no 4 change is by far the most consequential
proposed. I do not believe it affects end user code except for those who
inherit from error_code and override message() - surely a very, very
tiny number of people - but it sure as hell breaks everybody who
implements a custom error code category if you change the category's
message() signature.

The number of people worldwide currently implementing their own error
categories is likely low, and me personally speaking feel that their
mild inconvenience is worth losing <string> from the header
dependencies. But if backwards compatibility were felt to be super
important, in error_code::message() you could try dynamic_cast to an
error_category2 first in order to utilise an
error_category2::message_view() function. If the dynamic_cast fails, you
statically cache the strings returned by error_category::message() and
return string_views of them.

One could also, of course, simply drop modification no 4 entirely.
Modifications 1 to 3 are likely safe to almost all existing C++. Only
modification 4 breaks anything.

>> Boost was originally intended as an incubator for C++ standard changes.
>> This ticks that box perfectly.
>>
>> Thoughts on feasibility?
>
> Even besides that my code is likely to be broken by this, I think this
> is a really bad idea. Sure, Boost was concieved as the playground for
> the features that are potentially later included into the standard, but
> it is also a major C++ library that is widely used in the industry.
> Breaking users' code willy-nilly does not do any good neither to Boost
> nor to its users. So no, no breaking changes to see how bad its smells
> afterwards, please.

This is an API breaking change being discussed. Code _might_ break
beyond custom error categories.

But I currently believe that code other than custom error categories
_won't_ break. We are changing the API in ways that I would be very,
very surprised if much real world code out there even notices.

Besides, there is precedent for standard library features in C++ 11
which came from Boost continuing to be evolved in Boost, whilst
retaining API compatibility, with said evolutions being mirrored by the
C++ standard later. All code which compiles now will still compile with
this modified Boost.System apart from custom error categories, this is
not in doubt. The question is whether all code will still function
exactly as before. This is what the trial would discover.

Finally, Boost has broken API much more severely than this in the past
as part of natural evolution (not always intentionally). If it's
preannounced that we're doing this, and we do it, I don't see a problem
here. Plenty of old APIs have been retired before. And besides, this is
for testing a proposed change to a future C++ standard. That's a great
reason to break API, if you're going to do it.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
>> In my code I'm using contextual conversion to bool extensively, e.g.
>> "if (err)" or "if (!err)". This is currently equivalent to comparing
>> against 0, so I assume it will be broken by this change.
>
> It will only be broken if you rely on `error_code( 0, some-category )`
> to contextually-convert to `false`. A default-constructed error_code, or
> one that's been cleared, will still be `false`.
>
> A principled approach would be to ask the category whether a code is
> `true` or `false`, but that might be complexity and overhead nobody needs.

I think it unavoidable myself (and hardly complex to implement). Only an
error category knows if some value or other means success or not.

There would be not much overhead if the category implementation marks
the function used final, as I expect it would.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> This latter "idiom" is obviously broken after NIall's suggested change
> though.

Maybe. It depends.

If your category defines 0 as success, then if(err) will return false,
as it should be.

If your code does:

err.assign(0, err.category());
if(err != error_code())
  ...

And if your category is system_category, then yes now you would be
broken, because a default constructed error code would have a null
category under my proposal. Not system_category as at present.

One could dispense with null_category, and use system_category, but with
an internal nullptr representation. My objection to that is that C++ 11
is assuming that on every possible OS out there, code 0 is always
success. I find that to be presumptuous, and I think it should be fixed.

>> I'm also not happy to have to convert that initialization to
>>
>>      err = error_code();
>>
>> because it loses information about the error category, which may be
>> useful if I want to print `err` to log even if it is a success.
>
> Interesting. You rely on there being different success error_codes? This
> is also in direct opposition to the requested change.

No, every code domain must be allowed to dictate what means success to it.

For example, NTSTATUS code have two degrees of success, and two degrees
of failure. The top two bits determine this, leaving 30 bits for values
of each degree. An ntkernel_category would therefore define all codes
with a value >= 0 as being success.

Note that right now under the present design, we cannot represent this
in <system_error>. NTSTATUS values meaning success which are not zero
are seen as failures by error_code and C++ 11. This annoys me, because
it's not right.

(Readers may not be aware of my
https://github.com/ned14/ntkernel-error-category)

> How would you suggest we solve the problem of zero being an error in
> some contexts?

I think the same way as all non-negative values being a success.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
>> What we'd like to do is to test whether some very mildly breaking
>> changes to <system_error> are so mild as to affect no users, and on that
>> basis propose WG21 to make those mildly breaking changes to
>> <system_error> in the next C++ standard. And to test this, we'd like to
>> modify Boost.System with those mildly breaking changes, ship a release
>> and see how many users complain. If it is zero, we have evidence for
>> WG21 that this is not a consequential change.
>
> The usual way is to announce the upcoming change in release nnn and then
> make the change in release nnn + 1. What is wrong with using this method
> in your case, if all parties are in agreement to do it ?

It goes without saying that this forthcoming change would be announced
one release ahead as per Boost custom. So, next release would have it
#ifdef'd off by default, following release #ifdef's it on by default. A
macro would allow users to select which implementation.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Andrey Semashev wrote:

> > 3, Make the default constructor constexpr, now possible. No code should
> > notice a difference, except less runtime code will be generated.
>
> Not sure there will be any difference in the generated code, since the
> constructor still has to initialize the int and the pointer.

constexpr guarantees static initialization, and therefore that no additional
code needs to run except for the initialization of the int and the pointer.
Specifically, that system_category() does not do anything else besides
returning a pointer. At present, its straightforward implementation
initializes a function-local variable, which is required to be thread-safe
and therefore requires synchronization.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Niall Douglas wrote:
> > A principled approach would be to ask the category whether a code is
> > `true` or `false`, but that might be complexity and overhead nobody
> > needs.
>
> I think it unavoidable myself (and hardly complex to implement). Only an
> error category knows if some value or other means success or not.
>
> There would be not much overhead if the category implementation marks the
> function used final, as I expect it would.

I'm not sure it would matter much in the general case whether the category
implementation has marked the function final or not; if the compiler doesn't
know the dynamic type of error_code::category(), it would need to issue the
virtual call.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Niall Douglas wrote:

> One could dispense with null_category, and use system_category, but with
> an internal nullptr representation.

nullptr is not necessary. Read my LWG issue.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [system] Would it be possible to trial a breaking change to Boost.System and see what happens?

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 01/12/18 18:43, Niall Douglas via Boost wrote:

> 2. Success becomes solely the default constructed error code, which is
> code zero and a new category of "null_category". This is internally
> represented by { 0, nullptr }, and thus makes the default constructor
> trivial which is highly desirable as it eliminates any compiler magic
> static fencing for the default constructor. Right now the default
> constructor uses system_category with value 0, and I suspect no code
> will notice this change either.

Does this mean that custom error categories have to change their
make_error_code(e) function to either return a default constructed
error_code in case the error value indicates success, or a custom
error_code otherwise?

In other words, today we do this:

   namespace my {
     std::error_code make_error_code(my::errc e)
     {
        return std::error(e, my::category());
     }
   }

Should that be changed to this?

   namespace my {
     std::error_code make_error_code(my::errc e) {
       if (e == my::success)
         return std::error_code();
       return std::error_code(e, my::category);
     }
   }

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