sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Commit_operation bug

    Scheduled Pinned Locked Moved Developers' Forum
    28 Posts 5 Posters 1.0k Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A Offline
      adabyron
      last edited by

      Hello,

      I am developing a plugin in which, at certain moment, I need to switch off the view refreshing, due to performance reasons. So I surround the affected code with Model.start_operation (with the flag disable_ui set to true) and Model.commit_operation. The problem is that I'm getting bug splats when doing the last call (the commit_operation one). Everything is ok until then.

      Any idea? The callings are not inside observers. I have some of then in my application, but they don't trigger during the execution of the affected code. I add and delete entities massively (the code is a backtracking algorithm), but as far as I know this is not supposed to be a problem...

      Thanks in advance,

      Ada

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        I've never had issues with .commit_operation. I suspect that the issue is related to the deletion of entities. You might be trying to interact with invalid entities. Is your code verifying that the entities you deal with is .valid?

        (I moved this topic to the Developers section for higher visibility amongst the other ruby developers - until we've gathered more data on what it could be.)

        Question: does it splat if you do not use start_operation?
        Does it splat if you set the disable_ui flag to false?

        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • TIGT Offline
          TIG Moderator
          last edited by

          You haven't got the Outliner window rolled-down have you ?
          This will splat if you are changing a lot of items that it might be showing...

          TIG

          1 Reply Last reply Reply Quote 0
          • A Offline
            adabyron
            last edited by

            Thank you for your answers

            thomthom: No, my code is not verifying the entities. I will fix this, but by the moment I answer your questions:

            Q: does it splat if you do not use start_operation? No.
            Q: Does it splat if you set the disable_ui flag to false? No.

            It only splats when I set the flag to true and I have to delete entities inside the affected code (I have checked this). But now I have noticed a stranger behavior: the view does not refresh until the end, even if I do not put the start_operation and commit_operation callings surrounding the code. I mean, after the backtracking algorithm I can see the result, but I need to put an active_view.refresh calling each time I modify the entities inside the code if I want to see the partial solutions. Does SU refresh the view periodically or just when the entities are changed? I'm a little confused. Anyway, with this behaviour I don't need setting the disable_ui flag to true, so my problem disappears...

            TIG: It splats with or without the Outliner window rolled-down.

            1 Reply Last reply Reply Quote 0
            • thomthomT Offline
              thomthom
              last edited by

              Scripts that does heavy processing can often prevent the SU UI to update - even though SU tries. Using the disable_ui flag simply ensures it does not try to refresh the UI - preserving performance.

              Thomas Thomassen — SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Also do not use entities C++ collections directly, make a Ruby Array copy of them, when your loops need to delete items.
                You cannot safely iterate and delete items from the C++ collections.
                entsA = model.entities.to_a
                or
                entsA = group.entities.to_a
                .

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • thomthomT Offline
                  thomthom
                  last edited by

                  Good point.

                  Thomas Thomassen — SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    In addition, some kind of begin .. rescue .. end structure might be used to trap errors, and call .abort_operation in the rescue clause(s), and maybe prevent the BugSplat!.

                    .. maybe something like this?

                    
                    begin
                      model.start_operation("Task",true)
                      entsA = model.entities.to_a
                      entsA.each do |e|
                        # do stuff 
                      end
                      model.commit_operation
                    rescue
                      model.abort_operation
                    end
                    

                    Anyone have a better example of a basic "operational" block, with error trapping ??

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      That's as simple, and classic, example as it gets.

                      Thomas Thomassen — SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        Jim
                        last edited by

                        I think that in order to catch all classes of exceptions, you need to explicitly give an argument to the rescue clause:

                        
                        ...
                        rescue Exception => e
                        puts e.message
                        puts e.backtrace
                        end
                        
                        

                        Or use the appropriate type of Exception, such as LoadError, etc. I don't know how you are supposed to know what type of exception to expect, though.

                        Hi

                        1 Reply Last reply Reply Quote 0
                        • thomthomT Offline
                          thomthom
                          last edited by

                          Doesn't it do that be default?

                          Thomas Thomassen — SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • J Offline
                            Jim
                            last edited by

                            Back on topic - i would guess, as Dan said, you are probably changing (deleting items from) the collection as you iterate it; which is a no-no.

                            Hi

                            1 Reply Last reply Reply Quote 0
                            • J Offline
                              Jim
                              last edited by

                              I thought, with no argument, that rescue would catch Exceptions of type StandardError, which is probably what is wanted most of the time. But a LoadError and a SyntaxError would not be handled by default.

                              And I will add that I seem to have got in the habit of using the form I gave as an example, even though it may not be appropriate in all situations.

                              Hi

                              1 Reply Last reply Reply Quote 0
                              • Dan RathbunD Offline
                                Dan Rathbun
                                last edited by

                                I believe the rescue clauses' argument list works like the .kind_of? method, in that it is a conditional test that returns true for the exception class named, OR if the named class is a superclass of the actual exception class. (The testing begins at the actual class level, and "walks" the ancestry backward "up the family tree" of superclasses until it the named class is reached. Using Exception as the argument would always execute the rescue clause, as it is the ancestor of ALL exception subclasses.)

                                Multiple rescue clauses can be defined one after the other, similar to if ... elsif .. elsif ... else ... end statements.

                                Also more than one Exception class can be listed for each rescue clause.

                                Finally we can use the global $! to access the exception instead of creating a local via => var, but that's just a matter of personal style.

                                See: http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html

                                I'm not here much anymore.

                                1 Reply Last reply Reply Quote 0
                                • A Offline
                                  adabyron
                                  last edited by

                                  Dan and Jim: No, I'm not deleting entities as I iterate over the C++ collection. I delete the entities using object attributes, that is, I have something like this:

                                  
                                  class Shape
                                  
                                    attr_accessor ;group
                                  
                                    ...
                                  
                                    def erase()
                                      Sketchup.active_model.entities.erase @group
                                    end
                                  
                                  end
                                  

                                  At certain moment, I need to erase all the shapes, so I iterate over MY array of shapes:

                                  shapes.each { |s|
                                    s.erase
                                  }
                                  

                                  thomthom: OK, I didn't know that heavy scripts often prevent the UI to refresh.

                                  By the moment I'm happy with this behavior. Moreover, I have been told to refresh the UI, so the user can see the steps the algorithm is taking (how the entities are added and erased): I don't need to preserv performance any more. Everything is ok (no bug splats at all) when I don't use start_operation and commit_operation.

                                  In case I need to preserv performance again, I will make use of the begin.. rescue.. endidea 😉

                                  Thank you very much 😄

                                  1 Reply Last reply Reply Quote 0
                                  • thomthomT Offline
                                    thomthom
                                    last edited by

                                    But what about the undo stack? If you do not wrap your code in *_operation you get lots of small operations on your undo stack instead of one undoable step. Are you sure your users would be ok with this?

                                    Thomas Thomassen — SketchUp Monkey & Coding addict
                                    List of my plugins and link to the CookieWare fund

                                    1 Reply Last reply Reply Quote 0
                                    • A Offline
                                      adabyron
                                      last edited by

                                      thomthom: I have a command that resets the plugin, which users may use. By the moment I'm not worrying about the undo stack, but this is a future task...

                                      But I have just realized one thing:

                                      Sometimes, when I close SketchUp after using my plugin, I get a bug splat. Maybe it is probably due to the same reasons, I mean, when closing SU, the current operation commits, isn't it?

                                      I didn't give it importance at the beginning, because I couldn't reproduce the conditions in which the bug arised... The fact is that, now I realize, everything is OK if I don't delete entities. I have always thought that the bug was some consequence of using EntitiesObservers.

                                      I have some groups.entities in my plugin with this kind of observers attached, but these groups aren't the ones I delete inside the previous affected code. When I need to erase them (outside this code), I check if they have an attached observer and in that case I first remove the observer and then I erase the group.

                                      I have also an EntitiesObserver attached to Sketchup.active_model.entities, which only defines the onElementModified method. This method only does something when the modified entity ID is inside an internal list (there are few entities inside this list).

                                      These observers don't make changes inside the model. Anyway, might them be the source of all my problems?

                                      1 Reply Last reply Reply Quote 0
                                      • thomthomT Offline
                                        thomthom
                                        last edited by

                                        hmm... if you don't modify the model from within the events you usually should be fine. ..but there might be deviating causes. observers has always been a can of worms.

                                        I've tried to make an overview: http://forums.sketchucation.com/viewtopic.php?f=180&t=30793

                                        So - they could be the cause.

                                        Maybe we could get the attention of a Googler to look at this thread...

                                        Thomas Thomassen — SketchUp Monkey & Coding addict
                                        List of my plugins and link to the CookieWare fund

                                        1 Reply Last reply Reply Quote 0
                                        • A Offline
                                          adabyron
                                          last edited by

                                          Ok, they ARE the problem.

                                          I have just checked what happens if I don't attach an observer to Sketchup.active_model.entities, and everything is fine with *_operation.

                                          But I still have bug splats when closing SU. I bet this problem has to do with the other EntitiesObservers...

                                          By the moment I need this observers, so I will have to resign myself until the observers run smoothly...

                                          By the way, your overview was so useful to me some weeks ago (I was struggling with another bug). It is a great job 😉

                                          Thank you

                                          1 Reply Last reply Reply Quote 0
                                          • thomthomT Offline
                                            thomthom
                                            last edited by

                                            Which observers and which events did you use?
                                            Can you also briefly describe what you do with the events?
                                            (It'd be nice ot have this info in order to attempts to correlate the issues.)

                                            Btw - I just tried abort_operation to write out texture without adding to the undo stack or messing with the outliner:

                                            
                                            tw = Sketchup.create_texture_writer
                                            model = Sketchup.active_model
                                            
                                            model.start_operation('Write Textures', true)
                                            
                                            tmp = model.definitions.add('Temp_TextureWriter')
                                            g = tmp.entities.add_group
                                            model.materials.to_a.each_with_index { |m,i|
                                              next if m.texture.nil?
                                              g.material = m
                                              tw.load( g )
                                              p tw.write( g, "c;/temp/mat_#{i}.png" )
                                            }
                                            
                                            model.abort_operation
                                            
                                            

                                            Notice that I make a temp component definition - and therefore do not add anything to the model's entities collection. In worst case you just end up with a temp definition with an empty group. which I think SU will purge automatically at some point.
                                            The code can be improved with error catching - but the concept works.

                                            Think I'll make a wrapper for doing things like this - calling a method with a block where everything inside the block is aborted and therefore not included in the undo stack.

                                            Thomas Thomassen — SketchUp Monkey & Coding addict
                                            List of my plugins and link to the CookieWare fund

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 1 / 2
                                            • First post
                                              Last post
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement