Jump to content

Throwing and Catching Exceptions With Grand Old Error Cluster


Recommended Posts

Hi,

I think I worked out something pretty cool today. LabVOOP doesn't natively support class typed errors. Nor does it support throwing and catching exceptions as most object oriented programming languages. I implemented ability to throw and catch exceptions that are class objects. When an exception is thrown, the exception object is flattened to string and stored to error cluster. When exception is catched, the error cluster is tried to unflatten. If unflatten fails, the error is propagated forward. If unflatten is succesful, error is catched and error cluster is cleaned. This way, exception handling very similar to other object oriented programming languages is achived.

There are many advantages in class based exceptions over the conventional error cluster. First, you are not limited to the error number to fully describe your error. Indeed you can store anything into your error class and that anything is available to you when you catch the error.

Second you can use exception hierarchies. In the example attached I have an exception hierarchy. File error is a child of IO error which is a child of general error. When File error is thrown, it can be catched as a file error but also as a IO error or general error if you don't have an error handler for file error. That is you can write very specific error handlers but also very generic error handlers to handle unhandled exceptions.

The exception technique is not perfect, but it is functional and seems to work quite well. It doesn't cause much runtime overhead unless exception is thrown, and in this case it doesn't really matter. What would be really needed is a wizard that lets you fast create a new exception class, would OpenG community be interested in writing one? Currently writing a new exception class requires defining a constructor and a catch method for the class. Constructor should call parent constructor. Catch method is of the same for for every class, but since LabVIEW doesn't support passing the dynamic dispatch wire trough unflatten string node, catch method cannot be inherited from ancestor classes. Additionally there may also be a class probe and other methods in any error class.

Download File:post-4014-1157401108.zip

Link to comment

So, a suggestion that's been knocking around the R&D team for a bit....

I've mentioned several times (during the beta testing, at NI Week, in various forums) that the Error Cluster would make a great class ... if only we already had classes and were introducing the error code cluster for the very first time. Mutating all existing VIs and prims in some future version of LV would be nigh on impossible (I think). But...

The General Error Handler.vi takes in an error code cluster and makes it presentable ("human readable"). This VI follows a general pattern of 1) look up the code in the error code database and 2) display the source of the error with the translation. Now, several hacks have been applied in the past to embed information in the error code cluster. Specifically, the GEH.vi recognizes <append> and <err> tags. If these two tags appear in the source string then they are interpreted to mean "the source stops before this tag and everything after the tag should either be appended to the translation of the error code from the error code database or should replace the translation in the error code database (depending upon which tag is used)."

When DAQmx was rolling out, the hardware teams really wanted to have an error code cluster that would produce a graph in the General Error Handler.vi. We said No Way because the GEH.vi is too big already. We really can't afford to bloat it further with specialized dialogs for particular error codes. But what if we could dynamically dispatch somehow? Then we would only have VIs in memory for those errors types that actually might occur in a system -- that means specialized dialogs wouldn't be a global expense.

So the idea is to introduce an <obj> tag. Everything before the tag is the source of the error. Everything after the tag is a flattened object inheriting from ErrorDescription.lvclass or whatever name we make up. Then we could have the core of the GEH -- where the error code gets translated and put into a dialog -- be a dynamic dispatch. If no <obj> tag is encountered, construct a default error description object which does what the GEH does today.

The nice aspect of this is that non-LabVOOP users would get the advantages of object dispatching and specialized error types without ever having to be aware of them.

I have no idea what the performance would be like. I haven't had time to prototype the idea. But in combination with your throw/catch suggestion it might be a better way to handle errors in LV.

Link to comment
So, a suggestion that's been knocking around the R&D team for a bit....

Sounds great and even very simple to implement. Can we expect this to be implemented already in LabVIEW 8.2(0).1 :)

So the idea is to introduce an <obj> tag. Everything before the tag is the source of the error. Everything after the tag is a flattened object inheriting from ErrorDescription.lvclass or whatever name we make up.

Do you think there would be a default error code for error objects?

Then we could have the core of the GEH -- where the error code gets translated and put into a dialog -- be a dynamic dispatch. If no <obj> tag is encountered, construct a default error description object which does what the GEH does today.

Do you think it would be techically possible to unflatten a flattened object directly into dynamic dispatch wire? This would simplify my implementation a lot.

I have no idea what the performance would be like.

When no errors are thrown all the catch nodes just pass the error cluster trough them and only execute a single case structure. If these catch nodes are of subroutine priority, the are indeed executed quite fast. Of course if they are dynamically dispatched, then they cannot be of subroutine priority. However dynamic dispatching of catch nodes is not possible currently so, performance is guaranteed. Performance doesn't matter in cases when error has occurred as long as it's reasonable. I think it is very hard to slow things so much that the performance wouldn't be reasonable.

Link to comment
Sounds great and even very simple to implement. Can we expect this to be implemented already in LabVIEW 8.2(0).1 :)

No. Just because it is simple doesn't mean it is at all a priority. Any feature takes time, refactoring features take more time, and anything affecting the GEH takes a long long time because of the number of people who use it and have objections to any change in its behavior -- internal or external. Plus all the rest of your questions are exactly the sort of thing that would have to be brainstormed. We're a long way from even committing to something like this as a good idea, much less actually doing it.

You should consider any significant modifications of LV using OOP to be on more of a 10 year timespan than a 10 month timespan. The stability of the whole LabVOOP system has to be verified before LV starts relying on it generally. New features can develop and dodge around bugs. Refactoring old stuff means the new has to work flawlessly.

Link to comment
No. Just because it is simple doesn't mean it is at all a priority. Any feature takes time, refactoring features take more time, and anything affecting the GEH takes a long long time because of the number of people who use it and have objections to any change in its behavior -- internal or external. Plus all the rest of your questions are exactly the sort of thing that would have to be brainstormed. We're a long way from even committing to something like this as a good idea, much less actually doing it.

You should consider any significant modifications of LV using OOP to be on more of a 10 year timespan than a 10 month timespan. The stability of the whole LabVOOP system has to be verified before LV starts relying on it generally. New features can develop and dodge around bugs. Refactoring old stuff means the new has to work flawlessly.

Well maybe you guys at NI should stop taking holidays off ;) andd get to work on this stuff .... sounds interesting , now if i could only get my hands on 8.2 , i am anxiously waiting...

Dan

Link to comment
No. Just because it is simple doesn't mean it is at all a priority. Any feature takes time, refactoring features take more time, and anything affecting the GEH takes a long long time because of the number of people who use it and have objections to any change in its behavior

Perhaps I'll just write later when I have more time an open GEH replacement that calls the original GEH if the error is not of class type. This in addition with the throw and catch example of mine is a great improvement for many. This can then be used by the community until NI decides to launch something.

We should decide on the following issues:

- What would be the error code for class type errors. I suggest we use single code for

all errors thrown

- Should we be able to throw also warnings, what about multiple warnings?

- What should we call the top most error class that all errors are derived form

- Is some kind of default error hierarchy needed?

- Do we need a wizard to create new error classes?

Link to comment
  • 6 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.