Sunday, October 28, 2012

Qt Transition – Error Lists

The remaining item that uses the List class are the error lists generated by the Table class constructor (for errors detected in the table entries).  This constructor added errors to an error list, and at the end of the constructor, if there were any errors, the constructor threw an exception containing the pointer to the errors list.  The token initialization routine also previously threw an exception for any token status errors detected, but this code was removed when the enum.awk script was implemented to generate the token status enumeration and it detects any errors.

Because there were two types of errors and both were handling errors the same way, an Error template was implemented that could be used for both code (table) and token status errors.  This template also handled outputting the errors using a print function that was passed to it.  This design was also rather complicated.  I mentioned previously that Qt did not support exceptions, but this was not correct.  Qt can be used with exceptions, but none of the Qt classes and functions throw exceptions themselves.

Since the exception and error template design was complicated, it was removed.  For the table initialization to be able to return errors, the code was moved from the constructor to a new initialization function.  As for the error list to return, the QStringList class was used.  This class is a specialized list class, equivalent to QList<QString>.

Hit Continue... for details of the new table initialization implementation.  All lists have now been replaced with Qt equivalents.  The list.h header file was removed (along with the program that tested lists).  The next replacement will be the various stacks.

[commit a27e456222]

Table Initialization

In the table initialization function, for each error detected (if any), a QString will be created with the formatted error message and then appended to the error list.  At the end of the function, the error list will simply be returned.  The calling routine will check if the returning list is empty (no errors detected) or it can do what is needed with the errors.  Currently the errors are simply output to the standard error output stream.

The previous implementation allocated the list to hold the errors.  At the end, if there were any errors in the list, it would throw an exception with the pointer to the allocated error list.  It was up to the caller to release this memory.  A pointer was used so that the entire error list was not returned by value.  It's not the best design to allocate in one location and release memory in another.

For the new implementation, the error list is simply a local variable.  While this would appear to return the entire list by value (why a pointer was used in the previous implementation), it does not because Qt container classes support a feature known as implicit sharing that actually passes a container by reference.

The way implicit sharing works is that when a copy occurs (variable assignment, passing as a argument to a function, or returning a value from a function), it is initially done by reference for efficiency.  It is not until the copy is modified does a physical memory copy take place.

In additional, Qt container classes maintain a reference count.  An actual copy only occurs if there is more than one reference to the original.  In the case of returning a value from a function, the reference is copied.  However, since the original goes out of scope, the reference count of the copy goes to one, so the caller can modify the variable holding the return value without an actual copy taking place (though in this case, the returning error list is not modified).

No comments:

Post a Comment

All comments and feedback welcomed, whether positive or negative.
(Anonymous comments are allowed, but comments with URL links or unrelated comments will be removed.)