[Effective C + +--029] is worth the effort of "exception safe"

Source: Internet
Author: User

Suppose there is a class of GUI menu that shows the background pattern, this class is used in a multithreaded environment, so it has a mutex (mutex) for concurrency control:

1 classprettymenu{2  Public: 3     ... 4     voidChangebackground (std::istream&imgsrc); 5     ... 6 Private: 7 mutex mutex;8image*Bgimage;9     intimagechanges;Ten };  One voidPrettymenu::changebackground (std::istream&imgsrc) A {  -     Lock(&mutex);  - Delete bgimage; the++imagechanges; -Bgimage =NewImage (IMGSRC); -Unlock (&mutex);  -}

From the point of view of exception security, this function is very bad. Because there are not two conditions that satisfy the exception security:

1. do not disclose any resources . The code above does not do this because once "new Image" causes an exception, the unlock is not executed, and the mutex is imgsrc forever.

2. data corruption is not allowed . If "New Image (Imgsrc)" Throws an exception, Bgimage points to an object that has been deleted, Imagechanges has been added, and no new image has been successfully installed.

It is easy to solve the problem of resource leaks because clause 13 has taught us to "Manage resources by object", while clause 14 escapes into lock class as a way to "ensure that the mutex is released in a timely manner":

1 void Prettymenu::changebackground (std::istream&23     Lock ml (&mutex);           //  45         ++6     new   7 }

One of the best things about "resource management classes" like lock is that they usually make functions shorter. Less code is better code because there is less chance of error.

The exception security functions (Exception-safe function) provide one of the following three guarantees:

1. Basic Commitment : If an exception is thrown, anything inside the program remains in a valid state. No object or data structure can be corrupted, and all objects are in an internally consistent state (for example, all class constraints continue to be met). The actual state of the program is, however, unpredictable. As in the example above Changebackground, if an exception is thrown, the Prettymenu object can either continue to have the original background image, or make it have a default background image, but the customer cannot anticipate which case. If you want to know, they might have to call a member function to learn what the background image was at that time.

2. strongly guarantee : If the exception is thrown, the program status does not change. If the function succeeds, it is completely successful, otherwise the program will revert to the state before the call function.

3. do not throw (nothrow) guarantee : Promise never throws an exception, because they are always able to complete the function they originally promised. All operations on built-in types (such as ints, pointers, and so on) provide nothrow assurance. With "Blank exception details" function must be nothrow function, in fact, not necessarily

1 int Throw // "Blank exception Details"

This is not to say that dosomething never throws an exception, but that if an exception is thrown, it will be a serious error and there will be a call to your unexpected function. In fact dosomething may not provide any exception guarantee at all. The Declaration of a function (including the exception details) does not tell you whether it is correct, portable, or efficient, and does not tell you whether it provides any exception security guarantees.

In general, you should want to provide the strongest guarantee that can be implemented. The Nothrow function is great, but it's hard for us to call any function that might throw an exception in the C part of the C + + domain at all. So for most functions, choice often falls between the basic guarantee and the strong guarantee.

For Changebackground, first, change from a built-in pointer of type image* to a smart pointer for resource management, and second, rearrange the order of statements within Changebackground, This allows the imagechanges to accumulate after the image is replaced.

1 classprettymenu{2     ... 3STD::TR1::shared_ptr<Image>Bgimage;4     ... 5 };6 7 voidPrettymenu::changebackground (std::istream&imgsrc)8 { 9     Lock ml (&mutex);Ten     Bgimage.reset (New Image (IMGSRC));  One++imagechanges; A}

It is no longer necessary to manually delete the old image until reset is called after it has been successfully generated by its parameters (that is, the result of the execution of "new Image (IMGSRC)"). The drawback is the parameter imgsrc. If the image constructor throws an exception, it is possible that the read marker of the input stream has been moved, and such removal is a visible state change to the rest of the program. So before solving this, only the basic point exception security guarantee is provided.

As a strategy, bridging mode or a pattern called Pimpl can be implemented:

Pimpl mode can refer to my C + + blog.

1 structpmimpl{2Std::tr1::shared_ptr<image>Bgimage;3     intimagechanges;4 }; 5 classprettymenu{6     ... 7 Private: 8 mutex mutex;9Std::tr1::shared_ptr<pmimpl>Pimpl;Ten };  One voidPrettymenu::changebackground (std::istream&imgsrc) A {  -     usingStd::swap; -Lock ml (&mutex);  theStd::tr1::shared_ptr<pmimpl> Pnew (NewPmimpl (*Pimpl));  -Pnew->bgimage.reset (NewImage (IMGSRC));//Modify a copy -++pnew->imagechanges; -Swap (Pimpl, pnew);//Displacement Data +}

Make all the necessary changes on that copy. If any modification action throws an exception, the source object remains unchanged. After all changes are successful, replace the modified copy with the original object in a swap that does not throw an exception

The implementation usually puts all "data of the subordinate object" from the original object into another object, and then assigns a pointer to the source object, pointing to the so-called implementation object (Implementation object, the copy).

Summary

1. Abnormal security functions (Exception-safe functions) occur immediately and do not disclose resources or allow any data structures to be corrupted. Such a function area is divided into three possible guarantees: basic type, strong type, non-throwing anomaly.

2. "Strong assurances" can often be achieved with copy-and-swap, but "strong assurances" are not achievable or meaningful for all functions.

3. The "Exception security guarantee" provided by the function is usually the highest of the weakest in the exception security guarantee for each function that it invokes.

[Effective C + +--029] is worth the effort of "exception safe"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.