Resource management scope termination
Ok I've pussy-footed around the topic, I'll try to draw at least one conclusion finally from one of my first entries in this series.
When you have a pattern of real explicit resource management, the API that's used to denote the end of the resource's lifetime from the point of view of your client must not be able to fail without catestrophic consequences.
By "catestrophic consequences" I mean the appropriate level of runtime termination. For a user mode program this is probably the process. For a kernel mode subsystem this generally would mean bugchecking/panicing/cutesy-bomb-ing the system.
Thus the error in the original program actually was that close_resource() returned an error code in the first place. The only "useful" error condition is if the resource pointer passed in was invalid which would have indicated a programming error, and in general the best course of action when these occur is to terminate the address space.
In conclusion, the right code for the original example actually is:
int do_work(char *psz) {
resource *pr = NULL;
int t;
if ((t = open_file_as_resource(&pr, psz)) != 0) return t;
if ((t = swap_order_of_bytes_in_resource(pr)) != 0) { close_resource(pr); return t; }
close_resource(pr);
return 0; // success
}
You will, of course, notice now that the semantics are very close to try/finally, destructors or IDisposable/using.
I never really got why people wanted to say that destructors can throw but that it invokes a function to terminate the program. Maybe it was just trying to guard against "throw ()" poisoning (ala const poisoning) down the call chain in a destructor? As long as the frames aren't unwound prior to the abnormal_termination() call I guess it's equivalent.
There is of course more to the contract than not failing but that's a topic for another day. We will also eventually notice that all teardown operations also have to follow this basic pattern, and worry about what kind of lock-inversion/deadlock scenarios can happen when teardown occurs while a lock is held.