⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acis_tutorials_(exception_handling).htm

📁 acis说明文档
💻 HTM
📖 第 1 页 / 共 3 页
字号:
</td><td> Logically the same as EXCEPTION_CATCH(TRUE)</td></tr><tr><td> EXCEPTION_END</td><td> end of the exception block<p>resignal an exception if resignal_no&nbsp;!= 0</p></td></tr><tr><td> EXCEPTION_END_NO_RESIGNAL</td><td> end of the exception block<p>do not resignal an exception</p></td></tr></table><blockquote><b>Important:</b> <i>You should not lose ENTITIES or attempt to correct the ACIS data structure using the EXCEPTION_*** macros.  The ACIS data structure should be cleaned up by rolling back the model to a previously valid state.  This will be described below when we discuss the API_BEGIN / API_END macros.</i></blockquote><blockquote><b>Important:</b> <i>EXCEPTION blocks should never contain a return, goto, break, or other statement that would prematurely transfer control of out them.</i></blockquote><p><br /></p><a name="Aside:_How_to_Generating_Exceptions_and_Error_Messages"></a><h2> <span class="mw-headline"> Aside: How to Generating Exceptions and Error Messages </span></h2><p>In the Topology tutorial we introduced the <i>sys_error( )</i> and <i>find_err_mess( )</i> functions but didn't explain much about their usage.  sys_error( ) is used to "throw" an exception.  ("Throw" is in quotes because depending on the implementation, the C++ throw mechanism may or may not be utilized.)  <i>sys_error( )</i> has multiple signatures but we shall describe only the single argument signature of <i>sys_error( )</i> in this tutorial.  This should be sufficient for most applications.  </p><p><i>sys_error(err_mess_type)</i> takes a single argument, the error number.  ACIS contains an Error Messaging system that maintains a list of error numbers and corresponding error messages.  The Error Messaging system allows you to use, modify, and extend the lists of pre-defined error numbers and error messages.  Actually, from the developer's perspective, ACIS maintains a list of symbols and corresponding error messages.  At run time the symbols are given unique error numbers.  In your application you can obtain the error message corresponding to a given symbol by using the function <i>char const * find_error_mess(err_mess_type)</i> as we have demonstrated in previous tutorials.  The addition and modification of ACIS error messages is described in <a href="/r18/index.php?title=Error_Handling&amp;action=edit" class="new" title="Error Handling">Error Handling</a>.  An exhaustive enumeration of all ACIS error symbols, their associated error massage, and the file that contains them, you may refer to <a href="/r18/index.php?title=ACIS_Error_Messages&amp;action=edit" class="new" title="ACIS Error Messages">ACIS Error Messages</a>.  For the purposes of these tutorials we shall either propagate an already thrown exception or use the generic symbol: API_FAILED.</p><blockquote><b>Important:</b> <i>Calls to </i>sys_error( )<i> generate an exception; therefore, all </i>sys_error( )<i> calls must be within an EXCEPTION_*** block or a API_BEGIN / API_END block or else your application will abort when the exception is "thrown."</i></blockquote>  <a name="The_API_BEGIN_.2F_API_END_family_of_macros"></a><h2> <span class="mw-headline"> The API_BEGIN / API_END family of macros </span></h2><p>Previously we have mentioned the API_BEGIN / API_END macros can be used to roll back the model in the event of an exception.  Now we are ready to describe how this is done.  In <a href="/r18/index.php/Tutorial:ACIS_Tutorials_%28History_Streams%29" title="Tutorial:ACIS Tutorials (History Streams)">Tutorials (History Streams)</a> we shall describe what happens to the ACIS data structure during roll back and roll forward.  Now we are more interested in how to use these capabilities.</p><p>There are four sets of macros in the API_BEGIN / API_END macro family.  These are all defined in <i>api.hxx.</i>  </p><table class="wikitable"><tr><th> Macros</th><th> Description</th></tr><tr><td> API_BEGIN / API_END</td><td> Provide rollback behavior in the event of an exception</td></tr><tr><td> API_NOP_BEGIN / API_NOP_END</td><td> Similar to API_BEGIN / API_END<p>but always rolls back the (potentially nested) block</p></td></tr><tr><td> API_TRIAL_BEGIN / API_TRIAL_END</td><td> Similar to API_NOP_BEGIN / API_NOP_END<p>but rolls back the nested blockonly in the event of of an exception</p></td></tr><tr><td> API_SYS_BEGIN / API_SYS_END</td><td> Used by the ACIS system functions that manipulate<p>the history-related data structures</p></td></tr></table><blockquote><b>Important:</b> <i>These macros must always be used in matched pairs.</i></blockquote><blockquote><b>Important:</b> <i>Blocks formed by matched pairs of macros should never contain a return, goto, break, or other statement that would prematurely transfer control out of the block.</i></blockquote><p><br />The first three sets of macros are described in the subsections below.  The behavior of the system-related macros is beyond the scope of this tutorial.  Before we get into the description of these macros we need to define a couple terms.  </p><p>ACIS records sets of ENTITY changes on <i>BULLETIN_BOARDS</i>.  A BULLETIN_BOARD is the lowest level construct that can be rolled backward or forward.  When a BULLETIN_BOARD is rolled backward all the ENTITY changes recorded on it are undone.  When a previously rolled back BULLETIN_BOARD is rolled forward, the ENTITY changes are once again part of the model.  </p><p>During an operation ACIS may create <i>stacked BULLETIN_BOARDS</i>.  That is, BULLETIN_BOARDS within BULLETIN_BOARDS.  When the macro denoting the end of a stacked BULLETIN_BOARD is reached the ENTITY changes recorded on the stacked (inner) BULLETIN_BOARD will either be merged with the next higher level BULLETIN_BOARD or immediately rolled back. </p><a name="API_BEGIN_.2F_API_END"></a><h3> <span class="mw-headline"> API_BEGIN / API_END </span></h3><p>The API_BEGIN macro does several things for you.  If it is the outermost API_BEGIN it will open a BULLETIN_BOARD for you.  Each API_BEGIN starts an EXCEPTION block for you. (API_BEGIN includes an EXCEPTION_BEGIN and EXCEPTION_TRY.)  And all API_BEGINs declare an <i>outcome</i> called <i>result</i> for you. </p><p>Because all ENTITY changes must be on a BULLETIN_BOARD, all ENTITY changes must be within an API_BEGIN / API_END block.  A common ACIS programming error is to call a direct interface function that changes an ENTITY outside of an API_BEGIN / API_END block.  </p><p>Because API_BEGIN declares <i>result</i> for you, you should not redeclare <i>result</i> inside the block.  Redeclaring <i>result</i> inside the API_BEGIN / API_END block will hide the one declared in the API_BEGIN macro.  (<i>result</i> has been declared before the beginning of the EXCEPTION handling block so it will be in scope after the API_END.)   </p><p>Each API_END macro closes its EXCEPTION handling block, but it doesn't resignal any exception.  (API_END includes an EXCEPTION_CATCH and an EXCEPTION_END_NO_RESIGNAL.)  The outermost API_END records the value of <i>result</i> in the BULLETIN_BOARD, indicating success or failure of the API_BEGIN / API_END block.  </p><p>The processing of the BULLETIN_BOARD depends on the option <i>bb_immediate_close</i>.  If <i>bb_immediate_close</i> has a value of TRUE, then BULLETIN_BOARD is processed at when the API_END is reached.  If <i>bb_immediate_close</i> has a value of FALSE, then BULLETIN_BOARD is not processed until the next API_BEGIN statement.  Processing a BULLETIN_BOARD implies rolling back the changes if the operation failed, or closing the BULLETIN_BOARD and possibly merging it with other BULLETIN_BOARDs if the operation succeeded.  The default behavior of ACIS is to delay the processing of BULLETIN_BOARDs until the next API_BEGIN is encountered.  This provides a measure of safety if you should accidentally modify an ENTITY before the next API_BEGIN.   </p><p>There are several functions and options that affect the behavior of an API_BEGIN / API_END block.  These are enumerated below.   </p><ul><li> <i>api_logging( )</i></li><li> <i>set_logging( )</i></li><li> <i>bb_immediate_close</i> option</li><li> <i>bb_merge</i> option  (???)</li><li> <i>compress_bb</i> option</li></ul><a name="A_C.2B.2B_example"></a><h4> <span class="mw-headline"> A C++ example </span></h4><p>In this example we have created a function that generates a BODY that consists of the intersection of a cone and a prism.</p><pre class="source-cpp"><span class="kw5">logical</span> do_something<span class="br0">&#40;</span><span class="kw7">BODY</span> *&amp; my_body<span class="br0">&#41;</span><span class="br0">&#123;</span>  <span class="kw4">volatile</span> <span class="kw5">logical</span> success = <span class="kw2">TRUE</span>;&nbsp;  <span class="kw6">API_BEGIN</span>    <span class="kw7">BODY</span> *prism = <span class="kw2">NULL</span>;    result = api_make_prism<span class="br0">&#40;</span>..., prism<span class="br0">&#41;</span>;&nbsp;    <span class="kw7">BODY</span> *<span class="kw7">cone</span> = <span class="kw2">NULL</span>;    <span class="kw1">if</span><span class="br0">&#40;</span>result.<span class="me1">ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>      result = api_make_frustum<span class="br0">&#40;</span>..., <span class="kw7">cone</span><span class="br0">&#41;</span>;&nbsp;    <span class="co1">// prism is the tool. cone is the blank.  The result of</span>    <span class="co1">// the api_intersect( ) call is the blank (cone). The tool </span>    <span class="co1">// (prism) is deleted.</span>&nbsp;    <span class="kw1">if</span><span class="br0">&#40;</span>result.<span class="me1">ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>       result = api_intersect<span class="br0">&#40;</span>prism, <span class="kw7">cone</span><span class="br0">&#41;</span>;&nbsp;    <span class="co1">// If a NULL body is returned, then there was no overlap.</span>    <span class="co1">// We consider this a failure.  Force a rollback</span>    <span class="co1">// by setting result to a failing (non-zero) value.</span>&nbsp;    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw7">cone</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span>      result = <span class="kw5">outcome</span><span class="br0">&#40;</span>API_FAILED<span class="br0">&#41;</span>;  <span class="kw6">API_END</span>&nbsp;  <span class="co1">// Setup our return values.</span>  success = result.<span class="me1">ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;  my_body = <span class="kw7">cone</span>;&nbsp;  <span class="kw1">return</span> success;<span class="br0">&#125;</span></pre> <p>There are some significant points to note about this simple example:</p><ul><li> The variable <i>result</i> is used for determining the success or failure of the entire API_BEGIN / API_END block. It is even set to API_FAILED if the prism and cone do not intersect. By doing this, the API_END will examine <i>result</i> and, if it is non-zero, it will roll back all changes (assuming this is the outermost API_END and <i>bb_immediate_close</i> has a value of TRUE). </li><li> In the event of any type of failure, no cleanup is needed. The rollback will perform all cleanup. </li><li> There are no returns or gotos inside the API_BEGIN / API_END block. This is important because once an API_BEGIN / API_END block is entered, it must be exited through its corresponding API_END. </li></ul><p>Let us take this example one step further by considering how this routine might be called:</p><pre class="source-cpp"><span class="kw4">void</span> main<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><span class="br0">&#123;</span>  <span class="kw6">API_BEGIN</span>&nbsp;    <span class="kw7">BODY</span> * my_body;    <span class="kw5">logical</span> success = do_something<span class="br0">&#40;</span>my_body<span class="br0">&#41;</span>;    result = <span class="br0">&#40;</span>success == <span class="kw2">TRUE</span><span class="br0">&#41;</span>&nbsp;: <span class="kw5">outcome</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>&nbsp;? <span class="kw5">outcome</span><span class="br0">&#40;</span>API_FAILED<span class="br0">&#41;</span>;&nbsp;    <span class="co1">// If the result is not ok, no cleanup is  needed; all</span>    <span class="co1">// results will be rolled back when we pass through API_END.</span>&nbsp;    <span class="kw1">if</span> <span class="br0">&#40;</span>result.<span class="me1">ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>      api_del_entity<span class="br0">&#40;</span>my_body<span class="br0">&#41;</span>;&nbsp;  <span class="kw6">API_END</span><span class="br0">&#125;</span></pre>  <p>This illustrates that nesting of API_BEGIN/ API_END blocks is perfectly acceptable. However, there are important behavioral differences:</p><ul><li> If any failures occur within do_something( ), its API_END does NOT rollback the changes. Any rollback will occur at the outermost API_END, which is now the API_END in main.  Is it obvious that in this example a rollback will not occur if bb_immediate_close is FALSE?  </li><li> It is important for do_something( ) to propagate the knowledge of success or failure using its logical return value. It allows main() to determine success or failure and set its result appropriately. The knowledge of success or failure must be propagated upward through API_BEGIN / API_END blocks to ensure that the rollback occurs at the outermost API_END. </li></ul><p>This example does not demonstrate how to print error messages.  You may refer to previous tutorials, such as <a href="/r18/index.php/Tutorial:ACIS_Tutorials_%28Math_Classes%29" title="Tutorial:ACIS Tutorials (Math Classes)">Math Classes</a>, for an illustration of this.</p><a name="API_NOP_BEGIN_.2F_API_NOP_END"></a><h3> <span class="mw-headline"> API_NOP_BEGIN / API_NOP_END </span></h3><p>The API_NOP_BEGIN / API_NOP_END macros provide a means of performing a model changing operation and then immediately throwing away the changes.  API_NOP is pronounced "API_NO_OP" meaning the operation performed by the API is a NULL operation.</p><p>API_NOP_BEGIN opens a stacked BULLETIN_BOARD if another BULLETIN_BOARD is already open; otherwise, it simpl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -