Author Topic: Using Transactions In LISP  (Read 9098 times)

0 Members and 1 Guest are viewing this topic.

Peter Jamtgaard

  • Guest
Using Transactions In LISP
« on: December 09, 2013, 11:30:59 AM »
I had several interesting conversations with other programming colleagues at AU last week and I brought up the conversation about using Transactions in LISP.

What I found out was you can.

Exposed through the lispfunction method of .net you can create a transaction at the beginning of a command and commit or dispose of it at the end... It will roll back the command if disposed...

So I tried to create a way to change an object with a .net call to the top level transaction.

It works twice as fast as converting a entity to a vla-object and changing the object with the com.

Do you have a recommendation on testing software for lisp function speed?

I really think that a good .net dll could be developed to extend the power of lisp with .net.

I am always looking for suggestions of good functions...

Comments?

Peter

ymg

  • Guest
Re: Using Transactions In LISP
« Reply #1 on: December 09, 2013, 12:00:23 PM »
peter,

Not sure I follow you completely but it sounds very interesting.

Do you have any example maybe in pseudocode to light up my lantern?

ymg

ur_naz

  • Newt
  • Posts: 68
  • Made in Ukraine
Re: Using Transactions In LISP
« Reply #2 on: December 09, 2013, 12:29:26 PM »
There is no need to use backdoor in lisp. It is just inside AutoCAD. :-)

Peter Jamtgaard

  • Guest
Re: Using Transactions In LISP
« Reply #3 on: December 09, 2013, 04:46:46 PM »
I am not sure what you mean by backdoor.

To me good coding bypasses the command pipe and makes changes directly to the object model using com or some other methodology.

In this case, I want to be able to make multiple changes to the database, and avoid updating the database until I am done making the changes.

Using COM it updates the database on every property change.

Hence the reason to us transaction based changes, exposed from .net.

To manipulate the database from .net you need to use transactions.

That is one of the reasons that .net code is faster at runtime.

You could have 10000 changes and only one update of the database.

I am talking about adding transaction based manipulation of the database (like .net does) from lisp.

Instead of using (vlax-put objItem "color" 1)

Use these new lisp commands defined from .net

(transactionstart)
(propertyput entItem "colorindex" 1)
(transactioncommit)

Now if you only have one calls it probably is a wash, but if you have 10000 calls the transaction methodology would be MUCH faster.

p=


LE3

  • Guest
Re: Using Transactions In LISP
« Reply #4 on: December 09, 2013, 10:37:49 PM »
Sounds interesting...

Are those three LispFunction's, no?
 
On the PropertyPut - what are you using internally? for the property names? - Reflection? or have each of the Entity class basic properties names inside of a switch, list etc?
Can you pass any property name argument?
Or do you have to make for each of the desired properties a new method?

Glad, that you are taking the advantage of .NET.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #5 on: December 10, 2013, 12:10:18 AM »
Good idea! Though I can think of one snag: When you start a transaction you generally open one or more entities for write access. Since Lisp is running in the GUI thread, this means that those entities would then be unavailable to lisp - different thread (see it as if it's a different user wanting to change the objects which another user has open).

You might need to pass some ID code back-n-forth so the modify functions "know" to use the same thread in which the transaction was started.

Then again, I might be wrong - I've not tried sharing a transaction even between different DotNet programs, never mind between DotNet and Lisp. Only way to know for sure is to test it.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Using Transactions In LISP
« Reply #6 on: December 10, 2013, 12:39:16 AM »
Irne,
I don't imagine the algorithm design would allow user interaction while the transaction was active.

Gut level feel ;  I wouldn't allow the lisp to hold the transaction open between calls , even if it could be done simply. Cleaning up after an error may make it not worth the error.

Wish I knew what AutoDesk's intention was regarding AutoLisp delelopment and regarding Mac development and regarding AutoCAD 360
 ... but that IS asking a lot.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #7 on: December 10, 2013, 02:41:53 AM »
Irne,
I don't imagine the algorithm design would allow user interaction while the transaction was active.
Sorry, I think you misunderstood. I was using the 2 users working on the same thing as an analogy. The API sees 2 threads in the same light - that's why you sometimes get those issues where you can't edit something within a reactor (i.e. the reactor already has a read-lock on the entity, so your call-back function is not allowed to create a write-lock on the same entity when the reactor calls it).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #8 on: December 10, 2013, 02:49:01 AM »
Gut level feel ;  I wouldn't allow the lisp to hold the transaction open between calls , even if it could be done simply. Cleaning up after an error may make it not worth the error.
That is the main principle behind transactions: i.e. if an error occurs your lisp code should catch it through the *error* function and call the transaction's dispose method so it rolls-back any changes which has already been done. Else the transaction is committed when no error occurs, thus the database is updated only when the function has completed correctly.

True it is dangerous to leave the transaction open, but what else to do? You can't hold the programmer's hands all the time, they need to think for themselves too  :lmao:

Perhaps use something like DotNet's "using" idea: Create a function which takes a list of lisp cells for execution, then starts the transaction, runs through that lisp list and ensures it closes the transaction (no matter what the lisp inside has done or not).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Using Transactions In LISP
« Reply #9 on: December 10, 2013, 03:19:40 AM »

irne, I understand the purpose of a transaction.

Frankly, customisers currently don't make use of error trapping adequately .. I'd be bold enough to suggest that the majority don't understand how they work.
You're suggesting that another level of complication be added into the mix.

For me, it would be more beneficial adding .net functions that take lisp association lists of the keys,values to be changed and do all the grunt work in .net .. that way the complete operation can be wrapped without issue.

I'd consider leaving transactions open for a period of time not under the designers control is asking for trouble. 


//................
Peter,
If you're making changes to thousands  of objects often enough that the time taken is an issue you're using the wrong language to start with.
... getting expectations and capability mixed up in my opinion.

I thinks it's just an interesting intellectual exercise.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #10 on: December 10, 2013, 05:00:29 AM »
Frankly, customisers currently don't make use of error trapping adequately .. I'd be bold enough to suggest that the majority don't understand how they work.
You're suggesting that another level of complication be added into the mix.
I'm with you on that yes. Too many LSP's which cause stuff like OSMode / Highlight to go all wonky. Same thing could happen with these transactions I guess: i.e. user presses Esc, lisp fails to dispose/commit transaction ---->> user's unable to continue working in DWG as he's unable to modify anything until the transaction is ended (which will never end).

I'm just of the opinion, you shouldn't need to hamstring a language just because some (or even the great majority) of the "programmers" using it aren't doing it properly. At what point do you start thinking - this is too much power given to the programmer, versus where do you stop trying to make the language fool proof? Where you've turned all error handling into something synonymous with garbage collection or where you let the programmer handle all items which should be reset on an error?

For me, it would be more beneficial adding .net functions that take lisp association lists of the keys,values to be changed and do all the grunt work in .net .. that way the complete operation can be wrapped without issue.
That's a good idea too - though it's actually already implemented through ARX in the entmod routine for one entity at a time. This would basically be something like an entmod-multiple: i.e. send the function a list of dxf-data lists.

Actually this is where I think transactions could actually make Lisp more fool-proof. Rather than having the Lisp programmer write a full *error* defun which reverts all the modified items back to their original state - they now only need to call the single dispose on the transaction.

Or  :police: it might even be more advisable (read: More Fool Proof) to have a function which works like the using clause: Send the function a list of lisp instructions to perform on the list of entities. Then that DotNet function can wrap it all inside a transaction and roll back if it reaches an error. I.e. you implement the lisp eval calls inside a try-catch-finally block so you can ensure that (no matter what error's occurred) the transaction (and whatever other setting / reference you deem necessary) is rolled-back gracefully without the lisp programmer even needing to know about it.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Using Transactions In LISP
« Reply #11 on: December 10, 2013, 09:27:35 AM »
The code I posted will have unexpected results if UNDO is called. It will roll back to state before previous command was called.
See Comment Above.
-------------------Edit---------------

You would of course include error checking, abstract out the transaction part to be reusable, have well defined return values, etc......


Reflection will not give you great performance but you could do it that way


First one selected a circle and second one selected a line.
Quote
Command: (SetProps (car (entsel)) "Layer" "0" "ColorIndex" 4 "Radius" 10)
Select object: (0)

Command: (SetProps (car (entsel)) "Layer" "0" "ColorIndex" 4 "Radius" 10)
Select object: (nil)


The code above took 3 times as long to write code below. Did know how to get the ename or Objectid from entsel

It Worked.
Code - C#: [Select]
  1.         [LispFunction("SetProps")]
  2.         public ResultBuffer SetProps(ResultBuffer buffer)
  3.         {
  4.  
  5.             TypedValue[] args = buffer.AsArray();
  6.             int numberOfArguments = args.Length;
  7.             if (numberOfArguments > 2 & numberOfArguments % 2 != 0)
  8.             {
  9.                 ObjectId id = (ObjectId)args[0].Value;
  10.  
  11.                 try
  12.                 {
  13.                     using (Transaction trx = Doc.TransactionManager.StartTransaction())
  14.                     {
  15.                         DBObject dbo = trx.GetObject(id, OpenMode.ForWrite);
  16.                         Type type = dbo.GetType();
  17.                         PropertyInfo propInfo;
  18.                         string propName;
  19.                         for (int i = 1; i < numberOfArguments; i = i + 2)
  20.                         {
  21.  
  22.                             propName = args[i].Value as string;
  23.                             propInfo = type.GetProperty(propName);
  24.                             propInfo.SetValue(dbo, args[i + 1].Value, null);
  25.                         }
  26.                         trx.Commit();
  27.                     }
  28.                 }
  29.                 catch (System.Exception)
  30.                 {
  31.                     return new ResultBuffer(new TypedValue((int)LispDataType.Nil));
  32.  
  33.                 }
  34.  
  35.  
  36.             }
  37.  
  38.             return new ResultBuffer(new TypedValue((int)LispDataType.Int16, 0));
  39.         }
  40.  


« Last Edit: December 12, 2013, 01:19:34 AM by Jeff H »

LE3

  • Guest
Re: Using Transactions In LISP
« Reply #12 on: December 10, 2013, 09:35:28 AM »
^
A quick sample can be (no Reflection used) I am curios of what he used to pass the property name(s) or if it is target to each particular names:

Code - C#: [Select]
  1.         const int RSRSLT = 1; /* Result returned */
  2.         const int RSERR = 3; /* Error in evaluation -- no result */
  3.  
  4.         // Type of resbuf element
  5.         const int RTNONE = 5000; /* No result */
  6.         const int RTREAL = 5001; /* Real number */
  7.         const int RTPOINT = 5002; /* 2D point X and Y only */
  8.         const int RTSHORT = 5003; /* Short integer */
  9.         const int RTANG = 5004; /* Angle */
  10.         const int RTSTR = 5005; /* String */
  11.         const int RTENAME = 5006; /* Entity name */
  12.         const int RTPICKS = 5007; /* Pick set */
  13.         const int RTORINT = 5008; /* Orientation */
  14.         const int RT3DPOINT = 5009; /* 3D point - X, Y, and Z */
  15.         const int RTLONG = 5010; /* Long integer */
  16.         const int RTVOID = 5014; /* Blank symbol */
  17.         const int RTLB = 5016; /* list begin */
  18.         const int RTLE = 5017; /* list end */
  19.         const int RTDOTE = 5018; /* dotted pair */
  20.         const int RTNIL = 5019; /* nil */
  21.         const int RTDXF0 = 5020; /* DXF code 0 for ads_buildlist only */
  22.         const int RTT = 5021; /* T atom */
  23.         const int RTRESBUF = 5023; /* resbuf */
  24.         const int RTMODELESS = 5027; /* interrupted by modeless dialog */
  25.  
  26.         // Error return code
  27.         const int RTNORM = 5100; /* Request succeeded */
  28.         const int RTERROR = -5001; // Some other error
  29.         const int RTCAN = -5002; // User cancelled request -- Ctl-C
  30.         const int RTREJ = -5003; // AutoCAD rejected request -- invalid
  31.         const int RTFAIL = -5004; // Link failure -- Lisp probably died
  32.         const int RTKWORD = -5005; // Keyword returned from getxxx() routine
  33.         const int RTINPUTTRUNCATED = -5008; // Input didn't all fit in the buffer
  34.  

Code - C#: [Select]
  1.         [LispFunction("PutProperty")]
  2.         public void Swamp_PutProperty(ResultBuffer resultBuffer)
  3.         {
  4.             if (resultBuffer == null || resultBuffer.AsArray().Any(tv => tv.TypeCode != RTENAME && tv.TypeCode != RTSTR && tv.TypeCode != RTSHORT)) return;
  5.             var id = (ObjectId)resultBuffer.AsArray().FirstOrDefault(tv => tv.TypeCode == RTENAME).Value;
  6.             if (id == ObjectId.Null) return;
  7.             var propertyName = (string)resultBuffer.AsArray().FirstOrDefault(tv => tv.TypeCode == RTSTR).Value;
  8.             var propertyValue = (short)resultBuffer.AsArray().FirstOrDefault(tv => tv.TypeCode == RTSHORT).Value;
  9.             using (var transaction = AcadApp.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
  10.             {
  11.                 var entity = transaction.GetObject(id, OpenMode.ForWrite) as Entity;
  12.                 if (entity != null)
  13.                 {
  14.                     switch (propertyName.ToUpper())
  15.                     {
  16.                         case "LINEWEIGHT":
  17.                             break;
  18.                         case "VISIBLE":
  19.                             break;
  20.                         case "COLORINDEX":
  21.                             entity.ColorIndex = propertyValue;
  22.                             break;
  23.                     }
  24.                 }
  25.                 transaction.Commit();
  26.             }
  27.         }
  28.  

divtiply

  • Guest
Re: Using Transactions In LISP
« Reply #13 on: December 10, 2013, 10:54:54 AM »
I had several interesting conversations with other programming colleagues at AU last week and I brought up the conversation about using Transactions in LISP.

Take a look at Bricsys LispEx's:

vle-start-transaction
starts a database transaction; returns t on success
(vle-start-transaction)
only 1 transaction level is supported, nested calls have no effect

vle-end-transaction
finishes a previously started database transaction
(vle-end-transaction)
must be paired with (vle-start-transaction), even when nested; (vle-end-transaction) on a nested transaction level has no effect, only the outer-most (and only) transaction is finished; Lisp engine automatically ends an active transaction, i.e. in case or error, or when Lisp execution at top-level has finished

LE3

  • Guest
Re: Using Transactions In LISP
« Reply #14 on: December 10, 2013, 02:32:39 PM »
I just noticed that on autocad 2014 (windows - vanilla) you have some new autolisp (built-in) functions and in there is this one - btw:

http://docs.autodesk.com/ACDMAC/2012/ENU/filesALRMac/GUID-ED406069-97F9-4552-BBEF-9A02D06E6C1-203.htm

So, one can use:
Code: [Select]
(setpropertyvalue (car (entsel)) "color" 1)

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1454
  • Marco
Re: Using Transactions In LISP
« Reply #15 on: December 10, 2013, 04:09:37 PM »
I just noticed that on autocad 2014 (windows - vanilla) you have some new autolisp (built-in) functions and in there is this one - btw:

http://docs.autodesk.com/ACDMAC/2012/ENU/filesALRMac/GUID-ED406069-97F9-4552-BBEF-9A02D06E6C1-203.htm

So, one can use:
Code: [Select]
(setpropertyvalue (car (entsel)) "color" 1)
Louis, it is from 2012,     History:
AutoCAD 2014
New
findtrustedfile - Searches the AutoCAD trusted file paths for the specified file.
Changes
findfile - Searches the AutoCAD support and trusted file paths. Function was updated to search the new trusted applications paths.
AutoCAD 2013
New
vlax-machine-product-key - Returns the AutoCAD Windows registry path in the HKLM (HKEY_LOCAL_MACHINE).
Obsolete
vlax-product-key - Returns the AutoCAD Windows registry path.
AutoCAD 2012
New
command-s - Executes an AutoCAD command and the supplied input.
*pop-error-mode* - Error-handling function that ends the previous call to *push-error-using-command* or *push-error-using-stack*.
*push-error-using-command* - Error-handling function that indicates the use of the command function within a custom *error* handler.
*push-error-using-stack* - Error-handling function that indicates the use of variables from the AutoLISP stack within a custom *error* handler.
AutoCAD 2011
New
dumpallproperties - Retrieves an entity’s supported properties.
getpropertyvalue - Returns the current value of an entity’s property.
ispropertyreadonly - Returns the read-only state of an entity’s property.
setpropertyvalue - Sets the property value for an entity.
AutoCAD 2010
Changes
help - Invokes the Help facility. Function was updated to add support for HTML documentation.
AutoCAD 2009
New
initcommandversion - Forces the next command to run with the specified version.

LE3

  • Guest
Re: Using Transactions In LISP
« Reply #16 on: December 10, 2013, 04:36:07 PM »
Thank you Marco.... see I do not use autocad nor autolisp.  :kewl:

I use RealDWG nowadays....
« Last Edit: December 11, 2013, 08:14:51 AM by LE »

Peter Jamtgaard

  • Guest
Re: Using Transactions In LISP
« Reply #17 on: December 10, 2013, 06:28:29 PM »

irne, I understand the purpose of a transaction.

Frankly, customisers currently don't make use of error trapping adequately .. I'd be bold enough to suggest that the majority don't understand how they work.
You're suggesting that another level of complication be added into the mix.

For me, it would be more beneficial adding .net functions that take lisp association lists of the keys,values to be changed and do all the grunt work in .net .. that way the complete operation can be wrapped without issue.

I'd consider leaving transactions open for a period of time not under the designers control is asking for trouble. 


//................
Peter,
If you're making changes to thousands  of objects often enough that the time taken is an issue you're using the wrong language to start with.
... getting expectations and capability mixed up in my opinion.

I thinks it's just an interesting intellectual exercise.

Maybe an intellectual exercise...

Any competent .net programmer uses transactions all the time and manages them...

I see no reason why lisp programmers could not do the same.

I can make it so there are multiple transactions and subordinate transactions operating at the same time, and I can control them just like in .net.

Why not make the property change functions in lisp default to creating their own transactions but also accept a transaction as an argument (or something) allowing the code to function with one transaction instead of multiple.

I also think that objectid collections could replace selection sets etc...

LISP is a lightning fast programming language for coding and I see no reason why it couldn't also be fast at runtime as .net.

I understand errortrapping in both lisp and .net and am always thinking about how to make my functions more stable.

P=

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Using Transactions In LISP
« Reply #18 on: December 10, 2013, 06:42:48 PM »

I look forward to seeing the implementation and documentation.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #19 on: December 10, 2013, 11:36:29 PM »

I look forward to seeing the implementation and documentation.
Yes, me too  :lol: ... that is the main thing isn't it?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Using Transactions In LISP
« Reply #20 on: December 12, 2013, 01:31:39 AM »
What is the main reason for wanting to use transactions?

I would be considered a "newbie" when it comes to AutoLisp so I have no understanding of what problem transactions would solve in AutoLisp.

Transactions just wrap calls to open, close, cancel.

A transaction is a abstraction of a set of operations and you can achieve the same result performing the operations yourself saving cycles.

Transaction do not make your code faster they will make it slower. More code has to execute and more memory has to be allocated for a transaction to be used.  Transactions make writing code faster and easier to reuse and the time loss and extra complexity added is usually not enough compared to the gains of using them.

You could argue that it will only open a object once for all operations making it quicker or whatever but that is in the context of writing a reusable method or whatever but it still is a longer path for executing a set of operations.
You can achieve the same result from creating a collection and adding every object you open and checking to see if it is already open then returning object if it is or open it add to collection then return it. The built in transaction creates a new managed wrapper for each open so you could probably save time there by returning the same managed wrapper.

DocumentLocking is the mechanism used for setting Undo marks.

The is why the code I posted in earlier post will have unexpected results if UNDO is called. It will roll back to state before previous command was called.


I can make it so there are multiple transactions and subordinate transactions operating at the same time, and I can control them just like in .net.
I do not know of anyway of doing that because you only can use the Top Transaction or most recent transaction created per document.

The only way I could get it to behave correctly was to use UNDO command(Begin, End) or use DocumentManager.ExecuteInApplicationContext where a document lock would not be nested inside previous command.

Code - C#: [Select]
  1.         ResultBuffer returnbuffer = new ResultBuffer(new TypedValue((int)LispDataType.Nil));
  2.        
  3.        
  4.         [LispFunction("SetProps")]
  5.         public ResultBuffer SetProps(ResultBuffer buffer = null)
  6.         {
  7.             Application.DocumentManager.ExecuteInApplicationContext(ApplicationContextSetProps, buffer);
  8.  
  9.             return returnbuffer;
  10.         }
  11.  
  12.         private void ApplicationContextSetProps(object rbuffer)
  13.         {
  14.             ResultBuffer buffer = rbuffer as ResultBuffer;
  15.             if (buffer == null) return;
  16.             using (DocumentLock docLok = Doc.LockDocument(DocumentLockMode.ProtectedAutoWrite, "LISPSETPROPS", "LISPSETPROPS", true))
  17.             {
  18.                 TypedValue[] args = buffer.AsArray();
  19.                 int numberOfArguments = args.Length;
  20.                 if (numberOfArguments > 2 & numberOfArguments % 2 != 0)
  21.                 {
  22.                     ObjectId id = (ObjectId)args[0].Value;
  23.  
  24.                     try
  25.                     {
  26.                         using (Transaction trx = Doc.TransactionManager.StartTransaction())
  27.                         {
  28.                             DBObject dbo = trx.GetObject(id, OpenMode.ForWrite);
  29.                             Type type = dbo.GetType();
  30.                             PropertyInfo propInfo;
  31.                             string propName;
  32.                             for (int i = 1; i < numberOfArguments; i = i + 2)
  33.                             {
  34.  
  35.                                 propName = args[i].Value as string;
  36.                                 propInfo = type.GetProperty(propName);
  37.                                 propInfo.SetValue(dbo, args[i + 1].Value, null);
  38.                             }
  39.                             trx.Commit();
  40.  
  41.                         }
  42.                     }
  43.                     catch (System.Exception)
  44.                     {
  45.                        
  46.  
  47.                     }
  48.  
  49.  
  50.                 }
  51.  
  52.                 returnbuffer = new ResultBuffer(new TypedValue((int)LispDataType.Int16, 0));
  53.  
  54.             }
  55.         }
  56.  

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Using Transactions In LISP
« Reply #21 on: December 12, 2013, 01:58:31 AM »
What is the main reason for wanting to use transactions?
2 reasons:
  • As an added error handling idea. I.e. if an error occurred you roll back the transaction leaving everything in the state as it was before the transaction started. No actual changes were made to the database and the graphics hasn't refreshed - so it's actually "better" than trying to undo back to a previous state.
  • As an optimization: A transaction starts and turns the database & graphical updates off. This means you can make multiple changes to multiple entities within the transaction, and the overhead of actually updating the database and displaying those changes are left till the end. So instead of (the way it works now with the vla stuff and even entmod) edit one entity at a time and even one property of that entity, then update the databes & refresh the graphics, then move to the next and repeat .... turn off the updates, set the property values for each of the entities, turn the updates back on and refresh all changes in one go.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Using Transactions In LISP
« Reply #22 on: December 12, 2013, 03:54:33 AM »
Abort is much slower than a commit.
When you abort a transaction with many objects you can actually see the screen refresh a bunch.
Commit calls close on all objects at the same time - moves each objects undo file to global undo file and seems to refresh graphics once.
Abort calls cancel and uses temporary undo filer and undo file to set it back.

Each object gets its own temporary undo filer and undo file during a transaction, and I am only guessing but seems like when it runs through the objects reading the fields back in from the undo file it refreshes the graphics for each object.