From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17280 invoked by alias); 14 Jan 2002 00:04:58 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 17243 invoked from network); 14 Jan 2002 00:04:52 -0000 Received: from unknown (HELO localhost.cygnus.com) (24.114.42.213) by sources.redhat.com with SMTP; 14 Jan 2002 00:04:52 -0000 Received: from cygnus.com (localhost [127.0.0.1]) by localhost.cygnus.com (Postfix) with ESMTP id 6B1D73D1F for ; Sun, 13 Jan 2002 19:04:51 -0500 (EST) Message-ID: <3C4220A3.2010005@cygnus.com> Date: Sun, 13 Jan 2002 16:04:00 -0000 From: Andrew Cagney User-Agent: Mozilla/5.0 (X11; U; NetBSD macppc; en-US; rv:0.9.7) Gecko/20020103 X-Accept-Language: en-us MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [rfa/doc] Cleanups examples Content-Type: multipart/mixed; boundary="------------040102030005020106010807" X-SW-Source: 2002-01/txt/msg00369.txt.bz2 This is a multi-part message in MIME format. --------------040102030005020106010807 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 104 Hello, Eli suggested a review of the cleanups doco. Attatched hopefully helps. Ok to commit? Andrew --------------040102030005020106010807 Content-Type: text/plain; name="diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diffs" Content-length: 6042 2002-01-13 Andrew Cagney * gdbint.texinfo (Coding): Review Cleanups section. Examples examples. Document that a code-block should do or discard its cleanups before exit. Index: gdbint.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v retrieving revision 1.52 diff -p -r1.52 gdbint.texinfo *** gdbint.texinfo 2002/01/05 04:30:42 1.52 --- gdbint.texinfo 2002/01/14 00:00:35 *************** algorithms of @value{GDBN}. *** 4154,4167 **** @cindex cleanups Cleanups are a structured way to deal with things that need to be done ! later. When your code does something (like @code{malloc} some memory, ! or open a file) that needs to be undone later (e.g., free the memory or ! close the file), it can make a cleanup. The cleanup will be done at ! some future point: when the command is finished, when an error occurs, ! or when your code decides it's time to do cleanups. ! You can also discard cleanups, that is, throw them away without doing ! what they say. This is only done if you ask that it be done. Syntax: --- 4154,4169 ---- @cindex cleanups Cleanups are a structured way to deal with things that need to be done ! later. ! When your code does something (e.g., @code{xmalloc} some memory, or ! @code{open} a file) that needs to be undone later (e.g., @code{xfree} ! the memory or @code{close} the file), it can make a cleanup. The ! cleanup will be done at some future point: when the command is finished ! and control returns to the top level; when an error occurs and the stack ! is unwound; or when your code decides it's time to explicitly perform ! cleanups. Alternatively you can elect to discard the cleanups you ! created. Syntax: *************** Declare a variable which will hold a cle *** 4173,4204 **** @item @var{old_chain} = make_cleanup (@var{function}, @var{arg}); Make a cleanup which will cause @var{function} to be called with @var{arg} (a @code{char *}) later. The result, @var{old_chain}, is a ! handle that can be passed to @code{do_cleanups} or ! @code{discard_cleanups} later. Unless you are going to call ! @code{do_cleanups} or @code{discard_cleanups} yourself, you can ignore ! the result from @code{make_cleanup}. @findex do_cleanups @item do_cleanups (@var{old_chain}); ! Perform all cleanups done since @code{make_cleanup} returned ! @var{old_chain}. E.g.: @example make_cleanup (a, 0); ! old = make_cleanup (b, 0); ! do_cleanups (old); @end example @noindent ! will call @code{b()} but will not call @code{a()}. The cleanup that ! calls @code{a()} will remain in the cleanup chain, and will be done ! later unless otherwise discarded.@refill ! @findex discard_cleanups ! @item discard_cleanups (@var{old_chain}); ! Same as @code{do_cleanups} except that it just removes the cleanups from ! the chain and does not call the specified functions. ! @end table Some functions, e.g. @code{fputs_filtered()} or @code{error()}, specify that they ``should not be called when cleanups are not in place''. This --- 4175,4249 ---- @item @var{old_chain} = make_cleanup (@var{function}, @var{arg}); Make a cleanup which will cause @var{function} to be called with @var{arg} (a @code{char *}) later. The result, @var{old_chain}, is a ! handle that can later be passed to @code{do_cleanups} or ! @code{discard_cleanups}. Unless you are going to call ! @code{do_cleanups} or @code{discard_cleanups}, you can ignore the result ! from @code{make_cleanup}. @findex do_cleanups @item do_cleanups (@var{old_chain}); ! Do all cleanups added to the chain since the corresponding ! @code{make_cleanup} call was made. + @findex discard_cleanups + @item discard_cleanups (@var{old_chain}); + Same as @code{do_cleanups} except that it just removes the cleanups from + the chain and does not call the specified functions. + @end table + + Cleanups are implemented as a chain. The handle returned by + @code{make_cleanups} includes the cleanup passed to the call and any + later cleanups appended to the chain (but not yet discarded or + performed). E.g.: + @example make_cleanup (a, 0); ! @{ ! struct cleanup *old = make_cleanup (b, 0); ! make_cleanup (c, 0) ! ... ! do_cleanups (old); ! @} @end example @noindent ! will call @code{c()} and @code{b()} but will not call @code{a()}. The ! cleanup that calls @code{a()} will remain in the cleanup chain, and will ! be done later unless otherwise discarded.@refill ! ! Your function should explicitly do or discard the cleanups it creates. ! Failing to do this leads to non-deterministic behavior since the caller ! will arbitrarily do or discard your functions cleanups. This need leads ! to two common cleanup styles. ! ! The first style is try/finally. Before it exits, your code-block calls ! @code{do_cleanups} with the old cleanup chain and thus ensures that your ! code-block's cleanups are always performed. For instance, the following ! code-segment avoids a memory leak problem (even when @code{error} is ! called and a forced stack unwind occures) by ensuring that the ! @code{xfree} will always be called: ! @example ! struct cleanup *old = make_cleanup (null_cleanup, 0); ! data = xmalloc (sizeof blah); ! make_cleanup (xfree, data); ! ... blah blah ... ! do_cleanups (old); ! @end example ! ! The second style is try/except. Before it exits, your code-block calls ! @code{discard_cleanups} with the old cleanup chain and thus ensures that ! any created cleanups are not performed. For instance, the following ! code segment, ensures that the file will be closed but only if there is ! an error: ! ! @example ! FILE *file = fopen ("afile", "r"); ! struct cleanup *old = make_cleanup (close_file, file); ! ... blah blah ... ! discard_cleanups (old); ! return file; ! @end example Some functions, e.g. @code{fputs_filtered()} or @code{error()}, specify that they ``should not be called when cleanups are not in place''. This --------------040102030005020106010807--