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

0 Members and 1 Guest are viewing this topic.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • 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: 6150
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: 6150
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.