www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is anyone thinking about exception safety?

reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
I'm just working on some stuff with Lars for expanding the Open-RJ/D 
library (which will filter to all Open-RJ languages, I'm guessing) 
and while going through some of the code it's clear that some of it 
is not exception safe. Here's one of the functions we've come up 
with, so you can see the problem:

FYI: Open-RJ consists of Databases, with one or more Records, each 
of which consists of 0 or more Fields


    class Database
    {
        void addRecord(Record record)
        {
            m_records ~= record;
            foreach(Field field; record)
            {
                m_fields ~= field;
            }
            record.database = this;
        }

Anyone see the problem?

There are multiple allocations for extending the m_records and 
m_fields members of Database. If the concat of record onto m_records 
succeeds, but an exception is thrown in the opApply of Record, or 
one of the m_fields concatenations fails, then Database is invalid.

Obviously some working-to-the-side + swap idiom is required here. Is 
anyone taking such things into account, and possibly integrating 
such concerns into their code? Naturally this is something that we 
should make sure is properly handled in Phobos prior to 1.0
Apr 30 2005
next sibling parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Matthew schrieb am Sun, 1 May 2005 16:04:18 +1000:
 FYI: Open-RJ consists of Databases, with one or more Records, each 
 of which consists of 0 or more Fields


     class Database
     {
         void addRecord(Record record)
         {
             m_records ~= record;
             foreach(Field field; record)
             {
                 m_fields ~= field;
             }
             record.database = this;
         }

 Anyone see the problem?

 There are multiple allocations for extending the m_records and 
 m_fields members of Database. If the concat of record onto m_records 
 succeeds, but an exception is thrown in the opApply of Record, or 
 one of the m_fields concatenations fails, then Database is invalid.

 Obviously some working-to-the-side + swap idiom is required here. Is 
 anyone taking such things into account, and possibly integrating 
 such concerns into their code?

Depends. If I am dealing with IO or if opApply is/might be overloaded I try to reduce the damage, otherwise I only use contracts to detect problems. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCdH4Y3w+/yD4P9tIRApPCAJ9P+/xK78+PcHQ5RDwrylLvQ/2nXQCgk47k Nw7UN5EcV5tXnMQAFGdekBk= =MMCU -----END PGP SIGNATURE-----
Apr 30 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Thomas Kuehne" <thomas-dloop kuehne.thisisspam.cn> wrote in message 
news:p9bek2-lv6.ln1 lnews.kuehne.cn...
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1

 Matthew schrieb am Sun, 1 May 2005 16:04:18 +1000:
 FYI: Open-RJ consists of Databases, with one or more Records, 
 each
 of which consists of 0 or more Fields


     class Database
     {
         void addRecord(Record record)
         {
             m_records ~= record;
             foreach(Field field; record)
             {
                 m_fields ~= field;
             }
             record.database = this;
         }

 Anyone see the problem?

 There are multiple allocations for extending the m_records and
 m_fields members of Database. If the concat of record onto 
 m_records
 succeeds, but an exception is thrown in the opApply of Record, or
 one of the m_fields concatenations fails, then Database is 
 invalid.

 Obviously some working-to-the-side + swap idiom is required here. 
 Is
 anyone taking such things into account, and possibly integrating
 such concerns into their code?

Depends. If I am dealing with IO or if opApply is/might be overloaded I try to reduce the damage, otherwise I only use contracts to detect problems.

Not wanting to reignite the irrecoverability debate again, but how do contracts help with exception-safety? I couldn't begin to wonder.
May 01 2005
parent Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Matthew schrieb am Sun, 1 May 2005 17:11:22 +1000:
 "Thomas Kuehne" <thomas-dloop kuehne.thisisspam.cn> wrote in message 
 news:p9bek2-lv6.ln1 lnews.kuehne.cn...
 Matthew schrieb am Sun, 1 May 2005 16:04:18 +1000:
 FYI: Open-RJ consists of Databases, with one or more Records, 
 each
 of which consists of 0 or more Fields


     class Database
     {
         void addRecord(Record record)
         {
             m_records ~= record;
             foreach(Field field; record)
             {
                 m_fields ~= field;
             }
             record.database = this;
         }

 Anyone see the problem?

 There are multiple allocations for extending the m_records and
 m_fields members of Database. If the concat of record onto 
 m_records
 succeeds, but an exception is thrown in the opApply of Record, or
 one of the m_fields concatenations fails, then Database is 
 invalid.

 Obviously some working-to-the-side + swap idiom is required here. 
 Is
 anyone taking such things into account, and possibly integrating
 such concerns into their code?

Depends. If I am dealing with IO or if opApply is/might be overloaded I try to reduce the damage, otherwise I only use contracts to detect problems.

Not wanting to reignite the irrecoverability debate again, but how do contracts help with exception-safety? I couldn't begin to wonder.

They can help by catching violating arguments that are illegal and _should_ be impossible to pass to the function: # # Object[] argument = [SomeObject, null, AnotherObject]; # Depends very strong on the data you are dealing with and your coding style... Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCdIoW3w+/yD4P9tIRAmV3AKDQbFo4NishxreW+6EABT9TNJmhZwCgtPeF efqEzp6eMRPEjLFc8/lVaiA= =GBc5 -----END PGP SIGNATURE-----
May 01 2005
prev sibling next sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message 
news:d51rhj$20rp$1 digitaldaemon.com...
 I'm just working on some stuff with Lars for expanding the Open-RJ/D 
 library (which will filter to all Open-RJ languages, I'm guessing) and 
 while going through some of the code it's clear that some of it is not 
 exception safe. Here's one of the functions we've come up with, so you can 
 see the problem:

 FYI: Open-RJ consists of Databases, with one or more Records, each of 
 which consists of 0 or more Fields


    class Database
    {
        void addRecord(Record record)
        {
            m_records ~= record;
            foreach(Field field; record)
            {
                m_fields ~= field;
            }
            record.database = this;
        }

 Anyone see the problem?

 There are multiple allocations for extending the m_records and m_fields 
 members of Database. If the concat of record onto m_records succeeds, but 
 an exception is thrown in the opApply of Record, or one of the m_fields 
 concatenations fails, then Database is invalid.

 Obviously some working-to-the-side + swap idiom is required here. Is 
 anyone taking such things into account, and possibly integrating such 
 concerns into their code? Naturally this is something that we should make 
 sure is properly handled in Phobos prior to 1.0

Good point. I bet phobos hasn't been stressed in low-memory situations. I'll check out std.stream.
May 01 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:d52ib1$2ido$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message 
 news:d51rhj$20rp$1 digitaldaemon.com...
 I'm just working on some stuff with Lars for expanding the 
 Open-RJ/D library (which will filter to all Open-RJ languages, 
 I'm guessing) and while going through some of the code it's clear 
 that some of it is not exception safe. Here's one of the 
 functions we've come up with, so you can see the problem:

 FYI: Open-RJ consists of Databases, with one or more Records, 
 each of which consists of 0 or more Fields


    class Database
    {
        void addRecord(Record record)
        {
            m_records ~= record;
            foreach(Field field; record)
            {
                m_fields ~= field;
            }
            record.database = this;
        }

 Anyone see the problem?

 There are multiple allocations for extending the m_records and 
 m_fields members of Database. If the concat of record onto 
 m_records succeeds, but an exception is thrown in the opApply of 
 Record, or one of the m_fields concatenations fails, then 
 Database is invalid.

 Obviously some working-to-the-side + swap idiom is required here. 
 Is anyone taking such things into account, and possibly 
 integrating such concerns into their code? Naturally this is 
 something that we should make sure is properly handled in Phobos 
 prior to 1.0

Good point. I bet phobos hasn't been stressed in low-memory situations. I'll check out std.stream.

Cool. FWIW, I want to stress that I don't see this _in any way_ as a witch-hunt. I doubt that even Walter's fully exception-safe in all cases - if you are Walter, apologies. It's just something we should all start to think about sometime, maybe now, before 1.0 Cheers Matthew
May 01 2005
prev sibling parent Sean Kelly <sean f4.ca> writes:
In article <d51rhj$20rp$1 digitaldaemon.com>, Matthew says...
I'm just working on some stuff with Lars for expanding the Open-RJ/D 
library (which will filter to all Open-RJ languages, I'm guessing) 
and while going through some of the code it's clear that some of it 
is not exception safe.

So far I've just been focusing on exception behavior in the language itself. I posted a number of bug reports and such about exceptions in D, and am waiting on a response before I do much on the library side. As in C++ however, I expect RAII to be the most reasonable method to handle most of these situations... or finally blocks I suppose. Sean
May 02 2005