Discussion:
[Audacity-devel] Exception safety: not just stopping memory leaks
Paul Licameli
2017-03-22 01:40:25 UTC
Permalink
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.

This is harder than just scanning the code for new and delete, and it will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.

It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.

But those in-between levels cannot completely ignore errors: they must be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.

The general pseudo-code is:

Do X (with side-effects);
Do big, risky Y;
Undo X.

The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit any other exceptions.

Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a destructor
is a smart pointer.

I have lately pushed changes that move other "Undo X" steps into
destructors by other means.

One means is valueRestorer, where X is the setting of a variable.

Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.

Another somewhat common thing is locking and unlocking of a mutex, which is
best done with wxMutexLocker, or ODLocker.

Sometimes the "Undo X" step is to be cancelled, but only in case if exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release() on
a generalized std::unique_ptr (one with a second template parameter
supplied, the "deleter").

See my recent commits for abundant examples.

I am afraid someone will have to be a nag, examining all contributions, to
preserve the levels of safety I attained, and I hope others will learn
these not difficult principles well enough, that I don't have to be the
only nag.

Does this exhaust what it means to write exception-safe code? No, one must
also be familiar with the notions of weak, strong, and no-fail guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.

PRL
Gale Andrews
2017-03-22 03:21:02 UTC
Permalink
Paul,

Would it be worth (at least) referring to this on some or all of:

http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?

If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?



Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release() on a
generalized std::unique_ptr (one with a second template parameter supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions, to
preserve the levels of safety I attained, and I hope others will learn these
not difficult principles well enough, that I don't have to be the only nag.
Does this exhaust what it means to write exception-safe code? No, one must
also be familiar with the notions of weak, strong, and no-fail guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Darrell Walisser
2017-03-22 04:14:43 UTC
Permalink
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel region
exits. Yucky no doubt, but a similar problem would exist for any threaded
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
Post by Paul Licameli
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
Post by Paul Licameli
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
Post by Paul Licameli
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
Post by Paul Licameli
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
Post by Paul Licameli
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
Post by Paul Licameli
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
Post by Paul Licameli
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
Post by Paul Licameli
generalized std::unique_ptr (one with a second template parameter
supplied,
Post by Paul Licameli
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
Post by Paul Licameli
preserve the levels of safety I attained, and I hope others will learn
these
Post by Paul Licameli
not difficult principles well enough, that I don't have to be the only
nag.
Post by Paul Licameli
Does this exhaust what it means to write exception-safe code? No, one
must
Post by Paul Licameli
also be familiar with the notions of weak, strong, and no-fail
guarantees,
Post by Paul Licameli
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-22 05:30:21 UTC
Permalink
On Wed, Mar 22, 2017 at 12:14 AM, Darrell Walisser <
Post by Darrell Walisser
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel region
exits. Yucky no doubt, but a similar problem would exist for any threaded
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Thanks for your work with OpenMP, Darrell.

The uses of OpenMP are few enough to inspect, and I am not worried about
them. I made an exhaustive exploration of the call graph upward from the
functions from which I wanted to throw exceptions for errors in block
files. This did not take me into the few OpenMP loops.

True, you can't throw an exception out of a worker thread and into the main
thread. This actually was a concern in my work with exceptions.
Exceptions may be caught in the worker thread that reads and writes the
disk during playback and recording. The thread stops such exceptions from
going further. It uses the function CallAfter, supplied by wxWidgets, to
enqueue a piece of work for the main thread to do later at idle time, and
that is, to put up an error dialog alerting the user.

PRL
Post by Darrell Walisser
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
Post by Paul Licameli
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in
between
Post by Paul Licameli
not needing to be cluttered with testing and propagating of error
values.
Post by Paul Licameli
But those in-between levels cannot completely ignore errors: they must
be
Post by Paul Licameli
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
Post by Paul Licameli
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating
some
Post by Paul Licameli
memory and "undo X" is freeing it, and the tool to do that in a
destructor
Post by Paul Licameli
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
Post by Paul Licameli
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th
edition.
Post by Paul Licameli
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex,
which is
Post by Paul Licameli
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
Post by Paul Licameli
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
Post by Paul Licameli
generalized std::unique_ptr (one with a second template parameter
supplied,
Post by Paul Licameli
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
Post by Paul Licameli
preserve the levels of safety I attained, and I hope others will learn
these
Post by Paul Licameli
not difficult principles well enough, that I don't have to be the only
nag.
Post by Paul Licameli
Does this exhaust what it means to write exception-safe code? No, one
must
Post by Paul Licameli
also be familiar with the notions of weak, strong, and no-fail
guarantees,
Post by Paul Licameli
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Steve the Fiddle
2017-03-22 08:58:40 UTC
Permalink
I'm seeing *a lot* of compiler warnings from your new code Paul. Not a
problem in itself, but it makes it much harder to spot warnings from
my new code when there are vast numbers of warnings from existing
code.



Many of the warnings are trivial, such as:

../../src/blockfile/../xml/../FileException.h: In constructor
‘FileException::FileException(FileException::Cause, const wxFileName&,
const wxString&, const wxFileName&)’:
../../src/blockfile/../xml/../FileException.h:47:15: warning:
‘FileException::fileName’ will be initialized after [-Wreorder]
wxFileName fileName;
^
../../src/blockfile/../xml/../FileException.h:46:10: warning:
‘FileException::Cause FileException::cause’ [-Wreorder]
Cause cause;
^
../../src/blockfile/../xml/../FileException.h:20:13: warning: when
initialized here [-Wreorder]
explicit FileException
^



Some are difficult to avoid, but I think we can live with these if
there are not too many, such as:

../../include/audacity/Types.h: In constructor
‘sampleCount::sampleCount(long unsigned int)’:
../../include/audacity/Types.h:73:48: warning: narrowing conversion of
‘v’ from ‘long unsigned int’ to ‘sampleCount::type {aka long long
int}’ inside { } [-Wnarrowing]
sampleCount ( unsigned long v ) : value { v } {}



and then there are some where I find the code incomprehensible, such as:

../../src/xml/../AudacityException.h: In member function
‘AudacityException&
AudacityException::operator=(AudacityException&&)’:
../../src/xml/../AudacityException.h:42:58: warning: no return
statement in function returning non-void [-Wreturn-type]
AudacityException &operator = (AudacityException &&) {}


Steve
Post by Paul Licameli
On Wed, Mar 22, 2017 at 12:14 AM, Darrell Walisser
Post by Darrell Walisser
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel region
exits. Yucky no doubt, but a similar problem would exist for any threaded
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Thanks for your work with OpenMP, Darrell.
The uses of OpenMP are few enough to inspect, and I am not worried about
them. I made an exhaustive exploration of the call graph upward from the
functions from which I wanted to throw exceptions for errors in block files.
This did not take me into the few OpenMP loops.
True, you can't throw an exception out of a worker thread and into the main
thread. This actually was a concern in my work with exceptions. Exceptions
may be caught in the worker thread that reads and writes the disk during
playback and recording. The thread stops such exceptions from going
further. It uses the function CallAfter, supplied by wxWidgets, to enqueue
a piece of work for the main thread to do later at idle time, and that is,
to put up an error dialog alerting the user.
PRL
Post by Darrell Walisser
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release() on a
generalized std::unique_ptr (one with a second template parameter supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions, to
preserve the levels of safety I attained, and I hope others will learn these
not difficult principles well enough, that I don't have to be the only nag.
Does this exhaust what it means to write exception-safe code? No, one must
also be familiar with the notions of weak, strong, and no-fail guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-22 13:03:58 UTC
Permalink
Thank you Steve, I will fix these warnings.

PRL
Post by Steve the Fiddle
I'm seeing *a lot* of compiler warnings from your new code Paul. Not a
problem in itself, but it makes it much harder to spot warnings from
my new code when there are vast numbers of warnings from existing
code.
../../src/blockfile/../xml/../FileException.h: In constructor
‘FileException::FileException(FileException::Cause, const wxFileName&,
‘FileException::fileName’ will be initialized after [-Wreorder]
wxFileName fileName;
^
‘FileException::Cause FileException::cause’ [-Wreorder]
Cause cause;
^
../../src/blockfile/../xml/../FileException.h:20:13: warning: when
initialized here [-Wreorder]
explicit FileException
^
Some are difficult to avoid, but I think we can live with these if
../../include/audacity/Types.h: In constructor
../../include/audacity/Types.h:73:48: warning: narrowing conversion of
‘v’ from ‘long unsigned int’ to ‘sampleCount::type {aka long long
int}’ inside { } [-Wnarrowing]
sampleCount ( unsigned long v ) : value { v } {}
../../src/xml/../AudacityException.h: In member function
‘AudacityException&
../../src/xml/../AudacityException.h:42:58: warning: no return
statement in function returning non-void [-Wreturn-type]
AudacityException &operator = (AudacityException &&) {}
Steve
Post by Paul Licameli
On Wed, Mar 22, 2017 at 12:14 AM, Darrell Walisser
Post by Darrell Walisser
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel
region
Post by Paul Licameli
Post by Darrell Walisser
exits. Yucky no doubt, but a similar problem would exist for any
threaded
Post by Paul Licameli
Post by Darrell Walisser
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Thanks for your work with OpenMP, Darrell.
The uses of OpenMP are few enough to inspect, and I am not worried about
them. I made an exhaustive exploration of the call graph upward from the
functions from which I wanted to throw exceptions for errors in block
files.
Post by Paul Licameli
This did not take me into the few OpenMP loops.
True, you can't throw an exception out of a worker thread and into the
main
Post by Paul Licameli
thread. This actually was a concern in my work with exceptions.
Exceptions
Post by Paul Licameli
may be caught in the worker thread that reads and writes the disk during
playback and recording. The thread stops such exceptions from going
further. It uses the function CallAfter, supplied by wxWidgets, to
enqueue
Post by Paul Licameli
a piece of work for the main thread to do later at idle time, and that
is,
Post by Paul Licameli
to put up an error dialog alerting the user.
PRL
Post by Darrell Walisser
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they
must
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
be
appropriately written to "dodge" in between the throw and the catch,
by
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but
instead,
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
should happen within a destructor, and should also be guaranteed not
to
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling
release()
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
on a
generalized std::unique_ptr (one with a second template parameter supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all
contributions,
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
to
preserve the levels of safety I attained, and I hope others will
learn
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
these
not difficult principles well enough, that I don't have to be the
only
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
nag.
Does this exhaust what it means to write exception-safe code? No,
one
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
must
also be familiar with the notions of weak, strong, and no-fail guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future
code
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Darrell Walisser
Post by Gale Andrews
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Darrell Walisser
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Darrell Walisser
2017-03-22 15:45:15 UTC
Permalink
Post by Paul Licameli
On Wed, Mar 22, 2017 at 12:14 AM, Darrell Walisser <
Post by Darrell Walisser
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel region
exits. Yucky no doubt, but a similar problem would exist for any threaded
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Thanks for your work with OpenMP, Darrell.
The uses of OpenMP are few enough to inspect, and I am not worried about
them. I made an exhaustive exploration of the call graph upward from the
functions from which I wanted to throw exceptions for errors in block
files. This did not take me into the few OpenMP loops.
​The threaded code uses WaveTrackCache​ which eventually calls into
BlockFile. But there is also new() which can throw, at the least. Do you
want to take it to that level at this time (account for exceptions thrown
by stl/new), or only our own exception throwing?
Paul Licameli
2017-03-22 15:54:46 UTC
Permalink
On Wed, Mar 22, 2017 at 11:45 AM, Darrell Walisser <
Post by Paul Licameli
Post by Paul Licameli
On Wed, Mar 22, 2017 at 12:14 AM, Darrell Walisser <
Post by Darrell Walisser
Maybe worth noting that OpenMP parallel regions cannot throw exceptions.
The suggested way to handle that, is to wrap the region in a try, catch
*all* exceptions, and save one of them to rethrow when the parallel region
exits. Yucky no doubt, but a similar problem would exist for any threaded
operation containing resource allocation. By this standard, some of the
OpenMP stuff done thus far is certainly not exception safe.
Thanks for your work with OpenMP, Darrell.
The uses of OpenMP are few enough to inspect, and I am not worried about
them. I made an exhaustive exploration of the call graph upward from the
functions from which I wanted to throw exceptions for errors in block
files. This did not take me into the few OpenMP loops.
​The threaded code uses WaveTrackCache​ which eventually calls into
BlockFile. But there is also new() which can throw, at the least. Do you
want to take it to that level at this time (account for exceptions thrown
by stl/new), or only our own exception throwing?
You mean the fetch from WaveTrackCache in CalculateOneSpectrum? See commit
38b8e57e4efa94a3eeb75c13023b83aeb5d894d1. WaveTrackCache::Get() now has a
non-throwing option to return zeroes in case of failure. I decided to use
that in drawing code (also in playback) for reasons unrelated to OpenMP,
but that's another good reason.

If operator new throws an exception, I consider that a catastrophic
situation from which we won't attempt recovery. The places where new is
invoked are just too numerous to reason about.

What I just said is not inconsistent with other ideas I have entertained
for using std::set_new_handler to mitigate low memory situations:
http://en.cppreference.com/w/cpp/memory/new/set_new_handler

Because the new_handler would be called within operator new, before an
exception is thrown.

PRL
Post by Paul Licameli
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
James Crook
2017-03-22 10:47:02 UTC
Permalink
+1 to what Gale said. I was going to suggest the same myself, with
preference for new page rather than just adding to the existing ones.

Particularly a new page such as 'Code Guarantees' to explain weak,
strong, and no-fail guarantees

--James.
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release() on a
generalized std::unique_ptr (one with a second template parameter supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions, to
preserve the levels of safety I attained, and I hope others will learn these
not difficult principles well enough, that I don't have to be the only nag.
Does this exhaust what it means to write exception-safe code? No, one must
also be familiar with the notions of weak, strong, and no-fail guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-22 12:08:46 UTC
Permalink
Post by James Crook
+1 to what Gale said. I was going to suggest the same myself, with
preference for new page rather than just adding to the existing ones.
Particularly a new page such as 'Code Guarantees' to explain weak,
strong, and no-fail guarantees
--James.
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
I have not read these wiki pages before. Should they become more
frequently referred to now?

The first mentiones "CVS etiquette" which sound obsolete.

PRL
Post by James Crook
Post by Gale Andrews
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
Post by Gale Andrews
Post by Paul Licameli
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in
between
Post by Gale Andrews
Post by Paul Licameli
not needing to be cluttered with testing and propagating of error
values.
Post by Gale Andrews
Post by Paul Licameli
But those in-between levels cannot completely ignore errors: they must
be
Post by Gale Andrews
Post by Paul Licameli
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
Post by Gale Andrews
Post by Paul Licameli
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating
some
Post by Gale Andrews
Post by Paul Licameli
memory and "undo X" is freeing it, and the tool to do that in a
destructor
Post by Gale Andrews
Post by Paul Licameli
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
Post by Gale Andrews
Post by Paul Licameli
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th
edition.
Post by Gale Andrews
Post by Paul Licameli
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex,
which is
Post by Gale Andrews
Post by Paul Licameli
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
Post by Gale Andrews
Post by Paul Licameli
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
Post by Gale Andrews
Post by Paul Licameli
generalized std::unique_ptr (one with a second template parameter
supplied,
Post by Gale Andrews
Post by Paul Licameli
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
Post by Gale Andrews
Post by Paul Licameli
preserve the levels of safety I attained, and I hope others will learn
these
Post by Gale Andrews
Post by Paul Licameli
not difficult principles well enough, that I don't have to be the only
nag.
Post by Gale Andrews
Post by Paul Licameli
Does this exhaust what it means to write exception-safe code? No, one
must
Post by Gale Andrews
Post by Paul Licameli
also be familiar with the notions of weak, strong, and no-fail
guarantees,
Post by Gale Andrews
Post by Paul Licameli
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Gale Andrews
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Gale Andrews
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-22 14:02:54 UTC
Permalink
I have added to

http://wiki.audacityteam.org/wiki/CodingStandards

I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.

This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?

PRL
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
Post by Paul Licameli
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
Post by Paul Licameli
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
Post by Paul Licameli
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
Post by Paul Licameli
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
Post by Paul Licameli
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
Post by Paul Licameli
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
Post by Paul Licameli
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
Post by Paul Licameli
generalized std::unique_ptr (one with a second template parameter
supplied,
Post by Paul Licameli
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
Post by Paul Licameli
preserve the levels of safety I attained, and I hope others will learn
these
Post by Paul Licameli
not difficult principles well enough, that I don't have to be the only
nag.
Post by Paul Licameli
Does this exhaust what it means to write exception-safe code? No, one
must
Post by Paul Licameli
also be familiar with the notions of weak, strong, and no-fail
guarantees,
Post by Paul Licameli
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
James Crook
2017-03-22 15:12:00 UTC
Permalink
Nice.
Worth adding RAII and a link to a definition of it online?
--james.
Post by Paul Licameli
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Post by Gale Andrews
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
Post by Paul Licameli
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
Post by Paul Licameli
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
Post by Paul Licameli
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
Post by Paul Licameli
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
Post by Paul Licameli
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
Post by Paul Licameli
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
Post by Paul Licameli
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
Post by Paul Licameli
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
Post by Paul Licameli
generalized std::unique_ptr (one with a second template parameter
supplied,
Post by Paul Licameli
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
Post by Paul Licameli
preserve the levels of safety I attained, and I hope others will learn
these
Post by Paul Licameli
not difficult principles well enough, that I don't have to be the only
nag.
Post by Paul Licameli
Does this exhaust what it means to write exception-safe code? No, one
must
Post by Paul Licameli
also be familiar with the notions of weak, strong, and no-fail
guarantees,
Post by Paul Licameli
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-22 15:27:39 UTC
Permalink
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
--james.
I have described the idea of RAII without using that term.

I think Stroustrup himself regrets that rather uninformative coinage. And
I think it is less important to say "resource acquisition is
initialization" but instead say "resource deallocation is destruction."
That is, it should have been RDID.

Should I start another Wiki page or no?

There is much to say, but if I say too much, I fear the page will not get
read. I never read this coding standard page myself, before today, and I
see I have not hewed to everything there.

I get it that Audacity has tolerated laxity about naming and spacing
conventions, which might annoy and deter some contributors if we didn't.
But this resource leakage stuff is to me really important -- a matter of
correctness and efficiency and clarity and maintanability, not just a
fiddly matter of style and taste.

PRL
Post by James Crook
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandardshttp://wiki.audacityteam.org/wiki/Qualityhttp://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Darrell Walisser
2017-03-22 15:58:41 UTC
Permalink
Post by Paul Licameli
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
--james.
I have described the idea of RAII without using that term.
I think Stroustrup himself regrets that rather uninformative coinage. And
I think it is less important to say "resource acquisition is
initialization" but instead say "resource deallocation is destruction."
That is, it should have been RDID.
Should I start another Wiki page or no?
​I think it would be a good idea. Based on my own experience it is very
difficult to do exception safety correctly. In addition to threads, a
common problem we had was throwing across incompatible DLLs (throwing from
callbacks or library hooks). Depends on the compiler, compiler flags etc to
determine if libraries are "compatible" or not. I my case we were unable to
throw across a C library from a C++ library.
Paul Licameli
2017-03-22 16:26:05 UTC
Permalink
On Wed, Mar 22, 2017 at 11:58 AM, Darrell Walisser <
Post by Darrell Walisser
Post by Paul Licameli
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
--james.
I have described the idea of RAII without using that term.
I think Stroustrup himself regrets that rather uninformative coinage.
And I think it is less important to say "resource acquisition is
initialization" but instead say "resource deallocation is destruction."
That is, it should have been RDID.
Should I start another Wiki page or no?
​I think it would be a good idea. Based on my own experience it is very
difficult to do exception safety correctly. In addition to threads, a
common problem we had was throwing across incompatible DLLs (throwing from
callbacks or library hooks). Depends on the compiler, compiler flags etc to
determine if libraries are "compatible" or not. I my case we were unable to
throw across a C library from a C++ library.
I hear you! See what I did at commit 6525bb18cf06

But that is a question about inserting catches at comparatively few places
to stop exception propagation.

I'm conveying something different: that when you write new C++, even in
the core of Audacity and not dealing with C libraries, you should be aware
of exception propagation through your functions as a pervasive possibility,
and make defensive coding habits pervasive too.

You may be as old as I am, having grown up with old procedural languages
like C which didn't have destructors or this exception handling stuff in
them, but it's not hard to adjust your habits now. (The freshman
programming course still taught Pascal when I was at university. But I
never took any programming courses anyway.)

PRL
Post by Darrell Walisser
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
David Bailes
2017-03-23 10:13:12 UTC
Permalink
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
for example:
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource

Couldn't we just follow these c++ core guidelines, and document which if
its rules we are not going to follow. It would save reinventing the wheel.

David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandardshttp://wiki.audacityteam.org/wiki/Qualityhttp://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-23 12:06:25 UTC
Permalink
Post by David Bailes
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource
Couldn't we just follow these c++ core guidelines, and document which if
its rules we are not going to follow. It would save reinventing the wheel.
I have not myself read that interesting document through, but surely,
coming from Stroustrup and Sutter, the advice must be excellent.

That may be useful to refer to, but I think it is also worth having one
short guide to what is most important, explaining some peculiarities of our
own code.

Such as: once explaining what the strong exception safety guarantee is,
then explaining how that is achieved in Audacity's editing operations.

PRL
Post by David Bailes
David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandardshttp://wiki.audacityteam.org/wiki/Qualityhttp://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-23 13:56:55 UTC
Permalink
I have updated this page, explaining safety guarantees and how I mean to
implement them.

Not sure where the boundary between "coding standards" and "hacker's guide"
should go, whether I go too deep into the weeds, but some part of this
should be well known to developers. Specifically, where I mention what
must be done in intermediate levels of call stack in editing operations.
This requires everyone's awareness and cooperation to maintain it.

http://wiki.audacityteam.org/wiki/CodingStandards
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource
Couldn't we just follow these c++ core guidelines, and document which if
its rules we are not going to follow. It would save reinventing the wheel.
I have not myself read that interesting document through, but surely,
coming from Stroustrup and Sutter, the advice must be excellent.
That may be useful to refer to, but I think it is also worth having one
short guide to what is most important, explaining some peculiarities of our
own code.
Such as: once explaining what the strong exception safety guarantee is,
then explaining how that is achieved in Audacity's editing operations.
PRL
Post by David Bailes
David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandardshttp://wiki.audacityteam.org/wiki/Qualityhttp://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Steve the Fiddle
2017-03-23 15:59:43 UTC
Permalink
Good to see some documentation about this.
I presume that the exclamation marks don't mean anything?

Steve
Post by Paul Licameli
I have updated this page, explaining safety guarantees and how I mean to
implement them.
Not sure where the boundary between "coding standards" and "hacker's guide"
should go, whether I go too deep into the weeds, but some part of this
should be well known to developers. Specifically, where I mention what must
be done in intermediate levels of call stack in editing operations. This
requires everyone's awareness and cooperation to maintain it.
http://wiki.audacityteam.org/wiki/CodingStandards
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource
Couldn't we just follow these c++ core guidelines, and document which if
its rules we are not going to follow. It would save reinventing the wheel.
I have not myself read that interesting document through, but surely,
coming from Stroustrup and Sutter, the advice must be excellent.
That may be useful to refer to, but I think it is also worth having one
short guide to what is most important, explaining some peculiarities of our
own code.
Such as: once explaining what the strong exception safety guarantee is,
then explaining how that is achieved in Audacity's editing operations.
PRL
Post by David Bailes
David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Paul Licameli
2017-03-23 16:34:32 UTC
Permalink
Post by Steve the Fiddle
Good to see some documentation about this.
I presume that the exclamation marks don't mean anything?
They are certainly not factorials.

"No naked new!" is a nice alliterative slogan easily remembered.

PRL
Post by Steve the Fiddle
Steve
Post by Paul Licameli
I have updated this page, explaining safety guarantees and how I mean to
implement them.
Not sure where the boundary between "coding standards" and "hacker's
guide"
Post by Paul Licameli
should go, whether I go too deep into the weeds, but some part of this
should be well known to developers. Specifically, where I mention what
must
Post by Paul Licameli
be done in intermediate levels of call stack in editing operations. This
requires everyone's awareness and cooperation to maintain it.
http://wiki.audacityteam.org/wiki/CodingStandards
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource
Couldn't we just follow these c++ core guidelines, and document which
if
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
its rules we are not going to follow. It would save reinventing the
wheel.
Post by Paul Licameli
Post by Paul Licameli
I have not myself read that interesting document through, but surely,
coming from Stroustrup and Sutter, the advice must be excellent.
That may be useful to refer to, but I think it is also worth having one
short guide to what is most important, explaining some peculiarities of
our
Post by Paul Licameli
Post by Paul Licameli
own code.
Such as: once explaining what the strong exception safety guarantee is,
then explaining how that is achieved in Audacity's editing operations.
PRL
Post by David Bailes
David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things.
But
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
tell me, other developers, if this gets the most important points
across
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should
there
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandards
http://wiki.audacityteam.org/wiki/Quality
http://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is
possible
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to
motivate
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few
appropriate
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they
must
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
be
appropriately written to "dodge" in between the throw and the catch,
by
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not
to
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex,
which
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling
release()
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all
contributions,
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps
and
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Post by Paul Licameli
Post by David Bailes
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Post by Paul Licameli
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Peter Sampson
2017-03-23 16:47:44 UTC
Permalink
Post by Paul Licameli
"No naked new!" is a nice alliterative slogan easily remembered.
As H.G.Wells wrote in"The History of Mr. Polly" - one of my favourite books:

"Allitrition's *[sic]* artful aid" ;-))
David Bailes
2017-03-24 09:40:21 UTC
Permalink
Post by Paul Licameli
Post by David Bailes
Post by James Crook
Nice.
Worth adding RAII and a link to a definition of it online?
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-resource
Couldn't we just follow these c++ core guidelines, and document which if
its rules we are not going to follow. It would save reinventing the wheel.
I have not myself read that interesting document through, but surely,
coming from Stroustrup and Sutter, the advice must be excellent.
That may be useful to refer to, but I think it is also worth having one
short guide to what is most important, explaining some peculiarities of our
own code.
I'm suggesting that the c++ core guidelines become the primary source of
guidance for coding in Audacity.
That obviously needs to be supplemented by the documenting of where we
choose to deviate from these guidelines, any additional guidelines, and
highlighting guidelines which are particularly relevant to the Audacity
code.

David.
Post by Paul Licameli
Such as: once explaining what the strong exception safety guarantee is,
then explaining how that is achieved in Audacity's editing operations.
PRL
Post by David Bailes
David.
Post by James Crook
--james.
I have added to
http://wiki.audacityteam.org/wiki/CodingStandards
I could write much more about detailed techniques of safenew, non-default
deleters in unique_ptr, shared and weak pointers, and other things. But
tell me, other developers, if this gets the most important points across
clearly.
This is only a beginning: I only talk about resource management, not all
the other things I lately said in email about exceptions. Should there be
another new page?
PRL
Paul,
http://wiki.audacityteam.org/wiki/CodingStandardshttp://wiki.audacityteam.org/wiki/Qualityhttp://wiki.audacityteam.org/wiki/Guide_for_Hackers ?
If not a section in the Hackers' Guide, would it justify its own
page in the For Developers category?
Gale
I am trying to ensure exception safety, at least wherever it is possible
that read and write operations on block files may fail.
This is harder than just scanning the code for new and delete, and it
will
be harder to maintain, if other contibutors are not aware of stricter
demands and introduce new un-safeties. And I don't know how to motivate
every contributor to have the patience read this email to the end.
It is cleaner to write code that throws on error, with a few appropriate
catches that recover from errors; and the many levels of stack in between
not needing to be cluttered with testing and propagating of error values.
But those in-between levels cannot completely ignore errors: they must
be
appropriately written to "dodge" in between the throw and the catch, by
ensuring cleanup of side-effects even when exceptions pass.
Do X (with side-effects);
Do big, risky Y;
Undo X.
The "Undo X" step should never be done in-line like that, but instead,
should happen within a destructor, and should also be guaranteed not to
emit
any other exceptions.
Fixing memory leaks is only one special case where "X" is allocating some
memory and "undo X" is freeing it, and the tool to do that in a
destructor
is a smart pointer.
I have lately pushed changes that move other "Undo X" steps into
destructors
by other means.
One means is valueRestorer, where X is the setting of a variable.
Another is finally, taken from The C++ Programming Language, 4th edition.
Not a built-in construct as in some other languages, but a function
definable in C++11, that lets you wrap any code at all in a lambda
expression, so that it executes in a destructor of an ad-hoc class.
Another somewhat common thing is locking and unlocking of a mutex, which
is
best done with wxMutexLocker, or ODLocker.
Sometimes the "Undo X" step is to be cancelled, but only in case if
exiting
the function along a "success" path; that is, the "Do X" step is
conditionally committed. I do this in some places by calling release()
on a
generalized std::unique_ptr (one with a second template parameter
supplied,
the "deleter").
See my recent commits for abundant examples.
I am afraid someone will have to be a nag, examining all contributions,
to
preserve the levels of safety I attained, and I hope others will learn
these
not difficult principles well enough, that I don't have to be the only
nag.
Does this exhaust what it means to write exception-safe code? No, one
must
also be familiar with the notions of weak, strong, and no-fail
guarantees,
in case of multi-step operations that might complete only some steps and
then fail, and I will be referring to these notions too in future code
comments. But this email is long enough now.
PRL
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
------------------------------------------------------------
------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
audacity-devel mailing list
https://lists.sourceforge.net/lists/listinfo/audacity-devel
Loading...