Welcome to MSDN Blogs Sign in | Join | Help

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.

Published Monday, May 02, 2005 6:51 PM by mgrier

Comments

# re: Resource management scope termination

Tuesday, May 03, 2005 2:17 PM by indranilbanerjee
This is the same, and an awful lot cleaner

int do_work(char *psz) {
resource *pr = NULL;
int t;
if ((t = open_file_as_resource(&pr, psz)) != 0) return t;
t = swap_order_of_bytes_in_resource(pr);
close_resource(pr);
return t;
}

# re: Resource management scope termination

Tuesday, May 03, 2005 2:40 PM by mgrier
Agreed; in any of these patterns you can usually apply this optimization to the last failing function call in the sequence.

I personally try not to do this for similar reasons to why people advocate using braces in all contexts that could be blocks - so that the first change introduces less extraneous deltas.
New Comments to this post are disabled
 
Page view tracker