Home
Reply
Regular Contributor
merrifie
Posts: 31

API_BEGIN / END

Are there clearer guidlines for when API_BEGIN and API_END are required?

From reading the documentation, I'm under the impression these macro wrappers are necessary for modeling functions. However, in practice they often appear to be required when simply accessing ACIS data.

It's also my understanding that these wrappers provide exception handling.  Program execution is returned to the location of API_END and the "result" object should be checked.  Seems straight forward.  However, in practice, I don't understand how the addition of these wrappers could prevent an error in the first place.  For example, I had some code without the wrappers that would occationally crash. We identified steps that would reliably reproduce the crash.  The problem was creating a 'new' attribute on a face. Since this could be considered modeling (as we're changing or adding to the face object), I added the wrapper macros. I expected the program to jump to API_END and find that result was not "ok".  To my surprise, the program run fine, does not jump to API_END and result is "ok".

There's more to API_BEGIN and API_END than meets the eye.  Does API_SYS_BEGIN_INTERNAL (behind API_BEGIN) provide internal error handling that actually causes problems when it's not set up properly?

I also have a question about how tightly it should be coupled with api routines. If I have a set of simple statements, they should be wrapped by the macros.  If I have the same set of statements in a loop construct, should the wrappers be inside the loop or is it sufficient (and more efficient?) to place the macros around the outside of the loop?

Thanks,

Mike Merrifield
Visitor
sbrooks57
Posts: 1

Re: API_BEGIN / END

[ Edited ]
This question has best been answered on the ACIS Alliance group, by Paul R. Wolfenbarger
I included most of his response below. The response is too long to post on the board.
 
The short answer to why your code started working with API_BEGIN and API_END is that it sets up
a Bulletin Board (BB) pointer that ACIS calls depend on (calls that
change the state of the model).  Without setting up the BB pointer
and you call internal ACIS calls that create BB entities you will
get a null pointer error.

 

Steve Brooks

 

 

-----Original Message-----
From: acis-alliance-bounces@cs.columbia.edu [mailto:acis-alliance-bounces@cs.columbia.edu]
      On Behalf Of Wolfenbarger, Paul R
Matthew,
 
Spatial does not use the standard memory functionality as you are aware.
The Bulletin Board system relies on a number of memory tricks to keep
regular new/malloc and delete/free from working on all items derived from
ENTITY (and a number which are not - you get to guess on those each time.)
This system was designed for the convenience of a CAD system (AutoCAD) and
is not designed for people running a simulation where roll back/forward
capabilities are of little or no importance.
 
How it works
 
Any call starting with api_ is wrapped in a macro set of API_BEGIN/END.  If
there is no open Bulletin Board, the BEGIN macro will open one, otherwise,
it opens a sub-BB which will get wrapped into the next higher level one.
These macros also start some error handling and declare a scope and an
outcome object for that error handling named result (so if you declare one
of your own be sure to use another name or scope it.)  The code in the
function then goes about creating and modifying stuff as it likes and the
memory system keeps a running log of it in the form of BB entries that are
actually copies of the entities at each modification/delete.  As you can
imagine, this adds a lot of memory in a hurry.  The API_END call then checks
result for errors, sets up a few other catch blocks, and ends the scope.  It
also ends the bulletin board or sub-board.
 
So how do we go about recovering this memory stored in the BB?  And what
happens in a call like yours where there is no BB open?
 
If there is no BB open, a number of calls will fail, but some may work.  The
bad news is that either way, the copies that belong on the BB were created
and now exist in limbo and cannot be deleted.  Spatial provides methods for
dealing with BB's such as api_note_state, api_delete_ds, api_change_state,
and a few others.  None of these will function if an active BB exists, so
they must be at a top level.  So if I want to remove the stored memory from
the BB system I can use something like.
 
   if (_global_api_level() == 0) // checks to see that a BB is not open
   {
      DELTA_STATE* ds = NULL ;
 
#ifndef NDEBUG
      cout << check_free_lists() << " " ;  // This spits out a large amount
                                              of memory debugging info
#endif
      outcome res = api_note_state(ds) ;
                    // retrieves the delta from the
                    // last time this was done till now - may cover several boards.
 
      error_handling(res, "noteState", "api_note_state" );
 
      if (ds)
      {
         res = api_delete_ds(ds) ; // asks the memory system to remove the
                                      boards in this delta state
                      //- NOTE: The memory is not returned to the operating
                          system, but only to the freelist
                      //- managed by the ACIS kernel.  This means the next
                          time you ask for memory it will be
                      //- allocated from the free list rather than having to
                          ask the OS for more memory.
         error_handling(res, "noteState", "api_delete_ds" );
      }
 
#ifndef NDEBUG      
      cout << check_free_lists() << endl ;  // again the debugging info so
you can see the difference.
   }
   else
   {
      cout << "\n WARNING! noteState() called from inside an API
function\n";
#endif
   } 
 
For the type of work you are doing, the simplest thing would be to remove
the memory subsystem entirely and let the simple and fast new/delete
functions from C++ (or malloc/free from C) do the work without any
additional programming right?  Not in my experience.  The freelist method is
considerably faster than the OS memory request are since large contiguous
memory block can be requested and optimal use strategies utilized.  So what
about the pain of calling all of the above code every time you use an api
function of your own or spatials?  There are essentially 3 choices.
 
1) API_NOP_BEGIN/API_NOP_END - This is a set of macros designed to do
something similar to the above work for you (actually tries not to store the
copies in the first place).  The problem is that there must be no higher
level bulletin board open (despite what any documentation might tell you),
although the leak is much smaller than what you would have without the NOP
and using the cleanup shown.
 
2) Re-compile the acis memory manager to eliminate this behavior.  The
mmgr.cxx and freelist.cxx files are given to you (as of acis 7 I believe),
so you can try re-working these.  A number of macros are present in the code
to affect the compilation including one to turn everything off
(-DMMGR_DISABLED.)  I did try this once and was not happy with the speed of
the results, and have never spent the time to try and get a better
combination of macros done (see the bewildering array of them in mmgr.hxx),
mainly because the NOP/cleanup processes work as well as they do.  This was
not available on acis 6.
 
3) initialize_base allows you to pass in new allocation routines that can
customize the memory system to your uses.  If I was a major long-running
consumer app, I might go this route, but the cost of getting this just right
for a small project or a student project is likely a bit much.
 
3a) ignore it and let the system recover things at exit.  I admit I do a
good bit of this as most of my apps do not run long enough for this to be a
problem, but I know that ITS can easily run into problems with long runs and
tight memory spaces on the parallel machines.
 
So we are left with something like
 
API_NOP_BEGIN
  hit* blarg = raytest_face(...) ;
API_NOP_END
 
Ok, so this covers memory that was used during the call you make to
raytest_face, but what about the memory returned from the function?  If you
do not do anything, it will be leaked.  If you have the above and then call
api_del_entity or delete on the hits will there be a problem with items put
on the BB?  Does it need to be inside the BEGIN/END macro or does it matter?
 
hit is derived from ACIS_OBJECT rather than ENTITY which should put it into
the freelist system, but not onto a bulletin board as that is done in the
ENTITY constructor.  So we should be able to delete them whenever we wish
taking the scoping of the API_NOP_BEBIN/END macros into account and using
the overloaded delete (just use ACIS_DELETE and you should be ok for future
changes.)  If you do not delete them, you get a typical heap-type leak
behavior with the exception that the memory is in the freelist rather than
the OS heap.  As always, this will be cleared up when the program exits (not
when you call api_stop_modeller as far as I can tell.)
 
----------------------------------------------------------------------------
Paul R. Wolfenbarger, P.E., M.S.
prwolfe@sandia.gov
 


Message Edited by sbrooks57 on 09-13-2007 12:03 AM
Visitor
prwolfe
Posts: 3

Re: API_BEGIN / END

Well I guess nothing ever goes away on the net...  This was actually aimed at a particular problem, but I hope it is useful for everyone and I am a bit embaressed to see it re-surfacing...  Tell me though is there a way to get the smiley's turned off when posting/reading code fragments?

Paul
Spatial Moderator
Stacey
Posts: 76

Re: API_BEGIN / END

Hello Community!
 
Jeff, one of our kernel developers who is a technical fellow here at Spatial, wanted to address some of the questions originally presented here.  Unfortunately for us (but great for him! :smileywink:) he is on vacation the rest of the week.  He asked me to submit his initial comments for your consideration, and he'll update when he returns if appropriate.
 
We hope this is helpful!
Stacey
 
Accessing ACIS entities by all but the most trivial methods may cause entity changes. This is mainly caused by what we call lazy data calculations, which include calculating bounding boxes, parameter ranges, and bspline approximations, among others. These calculations modify entities, which require a log of the changes in the form of bulletins. These bulletins are added to an open bulletin board, which is supplied by the API_BEGIN macro. (Bulletins and bulletin boards are fundamental parts of the ACIS history stream system.) Modifying entities without an open bulletin board causes an error that usually results in an abort call. (I say usually because there are cases where bulletins can be added to previously closed bulletin boards, see the “bb_immediate_close” option for more details.) Therefore, when in doubt … wrap entity access routines with API_BEGIN/END macros.

The macros also enable ACIS exception control, which allows us to identify and catch hard errors such as floating point exceptions and segmentation violations, as well as internal ACIS errors. We enable this behavior in the outermost API_BEGIN and restore the original settings in the outermost API_END. Both error control and change tracking help provide a robust transaction system that maintains the integrity of models during modeling operations. The entity changes logged in bulletins on the history stream are used to roll back a model after a failed operation, to provide undo/redo capabilities, and can be inspected to determine what changes occurred during an operation. These abilities come at the expense of memory. However, applications that do not require complete history for undo/redo purposes can automatically limit the amount of logging information retained to that of the current operation by disabling API logging with the api_logging function.

 

The ACIS documentation provides useful information about the API_BEGIN/END macros in the “History and Roll” section and in the “Extending the Application Procedural Interface” section.

Jeff

 

Regular Contributor
merrifie
Posts: 31

Re: API_BEGIN / END

This information helps a great deal. Thanks.

(Looking forward to the forum feature (Nov.?) where the OP can mark the thread as providing an answer or solution to a question.)

Mike