From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,1888e8caa20a2f2d X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newspeer1.nwr.nac.net!solnet.ch!solnet.ch!news-zh.switch.ch!switch.ch!cernne03.cern.ch!cern.ch!news From: Maciej Sobczak Newsgroups: comp.lang.ada Subject: Re: Controlled types and exception safety Date: Wed, 30 Nov 2005 17:19:23 +0100 Organization: CERN - European Laboratory for Particle Physics Message-ID: References: NNTP-Posting-Host: abpc10883.cern.ch Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-Trace: sunnews.cern.ch 1133367562 5892 (None) 137.138.37.241 X-Complaints-To: news@sunnews.cern.ch User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050922 Red Hat/1.7.12-1.1.3.2.SL3 X-Accept-Language: en-us, en In-Reply-To: Xref: g2news1.google.com comp.lang.ada:6684 Date: 2005-11-30T17:19:23+01:00 List-Id: Dmitry A. Kazakov wrote: >>Now, the interesting part: let's say that during adjustment (3.) some >>error happened (like low memory condition or whatever) that resulted in >>raising an exception > > ARM 7.6.1 reads: "It is a bounded error for a call on Finalize or Adjust to > propagate an exception. > [...] > For an Adjust invoked as part of an assignment operation, any other > adjustments due to be performed are performed, and then Program_Error is > raised." OK, that brings some light, but does not solve my problem. :) >>The canonical C++ way is to *first* make a copy of new value (because >>this is when errors might occur, so that even if they occur, there was >>no change in the destination object) and *then* inject the duplicate >>into the destination object, getting rid of its old state (and this is >>assumed to be nothrow). > > Here the semantics of "copy", "inject", "duplicate" is ill-defined. In > general, you can copy a set of bits, but you cannot an object without > defining it in the terms copy-constructor. When I said "copy" above (C++), I meant create a new object as a copy. This involves copy constructor. The point is that this new object is *separate* from the destination object (from what's on the left side of assignment operator), so even if there are errors, they do not influence any of the two objects which were originally involved. After this new helper object is constructed (which means: *successfully* constructed), it's "injected" in the destination object by means of swapping the bowels. It looks like this: class Stack { public: // other stuff, including copy constructor // ... // assignment operator with strong guarantee void operator=(const Stack &other) { Stack temp(other); // this can fail, but that does not // influence the "this" object swap(other); // exchange of bowels (cannot fail) // temp is cleaned up (cannot fail) } private: // bowels // ... void swap(Stack &other) { // exchange bowels with the other Stack // this never fails if bowels involve only // fundamental types or components that // themselves have nothrow swap } }; This idiom is very effective. > In Ada's case copy-constructor > is defined as Bitwise copy + Adjust. The assignment is defined as Finalize + Bitwise copy + Adjust. And it's the fact that Finalize comes first that bothers me. > Which is > equivalently means that in general case you cannot define any reasonable > semantics for its partial completion. Note that in the example above there is no "partial completion". On the contrary - either the operation completes successfully or it fails *wihout* modifying anything. Moreover, the scheme does not force me to ignore the error nor anything like this, I can let it go to the place where there's enough context to really handle it. >>What do you do to avoid surprises? > > Don't let exceptions propagate. What do you mean by "don't propagate"? What if there is an exception that was raised by the run-time (like low memory condition) in the middle of adjusting the whole stack? What should I do with the part that was aleady adjusted (duplicated)? What should I do with the part that was not yet adjusted? Should I clean up what's already done and leave the destination stack as empty and shut the exception up, thus preventing the higer-level code from properly handling it? Is it possible to have assignment with strong exception guarantee? -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/