[Gambas-user] WITH and FOR EACH across emulated collections (large post)

Fabien Bodard gambas.fr at ...626...
Mon Dec 27 09:51:51 CET 2010


2010/12/27 Bruce Bruen <bbruen at ...2308...>:
>
>   Hello all,
>
>   (gambas 2.22)
>
>   I am trying to build a persistence mechanism ala Ambler to decouple the
>   business logic from the persistence mechanism. I have done this
>
>   several times before in gambas with great success, but with the "rule" that
>   a
>
>   business-object instance can only represent a single row in the associated
>
>   database table. However, this time I am trying to include a way to allow
>
>   a single business-object instance to represent a set of database rows and
>
>   to provide the means to enumerate across the rows. In short, it changes the
>
>   business-object class into a psuedo collection.
>
>   I have attached a png showing the class structure. It has been simplified
>   very much to illustrate the problem I am having.
>
>   [cid:183244887 at ...2520...]
>
>   I  have  also  attached  a  test  project (as a "source archive") that
>   demonstrates the problems. These are
>
>   1) Use of "WITH" seems to decouple the _free() method
>
>   2) use of "FOR EACH ... NEXT" seems to decouple the _free() method and
>
>   introduces circular references.
>
>   The test project steps through a number of test cases. In each step, an
>   instance of a specific business-object class is created and an explicit
>   destruction request is issued
>
>   $employee = NEW Employee
>
>   ...
>
>   $employee = NULL
>
>   Between  these,  each test demonstrates a single type of access to the
>   business_object class instance, for example Test3 just prints the values of
>   the properties of the first row encountered in the database Result.
>
>   (The Main routine includes all the "STOP"s so that the output does not
>   become jumbled.)
>
>   Here is the output I get (with some comments in colour):
>
>   =============================
>
>   ----> Test 1 just creates a BO instance and then destroys it
>
>   BO destructor for Employee (2 references)
>
>   <---- Test 1 complete, explicit object destruction trace should be above
>   this line
>
>   This demonstrates that the destructor (_free) method is being called for the
>   explicit $employee=NULL line
>
>   =============================
>
>   ----> Test 2 creates a BO instance, loads it and then destroys it
>
>   Employee Load got 3 rows
>
>   BO destructor for Employee (2 references)
>
>   <---- Test 2 complete, explicit object destruction trace should be above
>   this line
>
>   Loading the multiple rows occurs properly and the destruct call works
>
>   =============================
>
>   ----> Test 3 creates a BO instance, loads it, uses it explicity and then
>   destroys it
>
>   Employee Load got 3 rows
>
>   Test 3 Ard01 Aaron Ardvaark 1001 45000
>
>   BO destructor for Employee (2 references)
>
>   <---- Test 3 complete, explicit object destruction trace should be above
>   this line
>
>   Here we just use the object in a simple manner, again destruct is OK
>
>   =============================
>
>   ----> Test 4 creates a BO instance, loads it, uses it via WITH and then
>   destroys it
>
>   Employee Load got 3 rows
>
>   Test 4 Ard01 Aaron Ardvaark 1001 45000
>
>   <---- Test 4 complete, explicit object destruction trace should be above
>   this line
>
>   BO destructor for Employee (2 references)
>
>   Here's the first problem, just by using WITH instead of directly referencing
>   the object variables has caused the _free() method to not be called on
>
>   $employee=NULL (I do see that it is called when the Test4 method exits
>   though, i.e. the runtime does know it has to free the references somehow.
>   But why is the explicit destruction ignored?
>
>   =============================
>
>   ----> Test 5 creates a BO instance, loads it, uses it explicity and then
>   destroys it (repeat Test3)
>
>   Employee Load got 3 rows
>
>   Test 5 Ard01 Aaron Ardvaark 1001 45000
>
>   BO destructor for Employee (2 references)
>
>   <---- Test 5 complete, explicit object destruction trace should be above
>   this line
>
>   This was just included to prove to myself that everything is still ok.
>
>   =============================
>
>   ----> Test 6 creates a BO instance, loads it, enumerates the set (using FOR
>   EACH & explicit property name) and then destroys it
>
>   Employee Load got 3 rows
>
>   Test 6 Ard01 Aaron Ardvaark 1001 45000
>
>   Test 6 Ban01 Bev Banana 1001 48500
>
>   Test 6 Fri01 Fanny Fricassee 1001 38920
>
>   <---- Test 6 complete, explicit object destruction trace should be above
>   this line
>
>   Here the explicit and implicit destructions are both ignored ( and this
>   causes
>
>   the final error below)
>
>   =============================
>
>   ----> Test 7 creates a BO instance, loads it, enumerates the set (manually)
>   and then destroys it
>
>   Employee Load got 3 rows
>
>   Test 7 0 Ard01 Aaron Ardvaark 1001 45000
>
>   Test 7 1 Ban01 Bev Banana 1001 48500
>
>   Test 7 2 Fri01 Fanny Fricassee 1001 38920
>
>   BO destructor for Employee (2 references)
>
>   <---- Test 7 complete, explicit object destruction trace should be above
>   this line
>
>   In this final test, where I use MoveNext rather than FOR EACH, everything
>   appears OK.
>
>   =============================
>
>   WARNING: circular references detected
>
>   _pEmployee (1)
>
>   Employee (1)
>
>   WARNING: 49 allocation(s) non freed.
>
>   When the program exits, I get the circular references problem
>
>   Hopefully, I have packed up the test project correctly and some kind soul
>   will confirm the above and be able to reply with what it is that I am doing
>   wrong.
>
>   The only thing I have been able to isolate is that the circular reference
>   appears the second time that Unmarshall is called from the Persistor _next()
>   method  at  line  143. If this call is commented out then the circular
>   references  do  not happen. The ingorances of the $employee=NULL still
>   continue though.
>
>   The test project is a very cut down version of the real dev project, so some
>   of the constructs used may appear odd, such as the use of dynamic object
>   creation. Please ignore the use of these as they do make sense in the real
>   project and have been proven OK in the other (single row) versions of this
>   design. The issues lie solely with "WITH" (where I cannot see how I have
>   disturbed it) and with FOR EACH (where I cannot understand what is causing
>   the circular references).
>
>   Thank you for reading this and many thanks in advance if you could find time
>
>   to help me with this.
>
>   --
>
>   best regards
>
>   Bruce Bruen
>
> ------------------------------------------------------------------------------
> Learn how Oracle Real Application Clusters (RAC) One Node allows customers
> to consolidate database storage, standardize their database environment, and,
> should the need arise, upgrade to a full multi-node Oracle RAC database
> without downtime or disruption
> http://p.sf.net/sfu/oracle-sfdevnl
> _______________________________________________
> Gambas-user mailing list
> Gambas-user at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gambas-user
>
>

Clearly, gambas miss a way to know the var name where are stored the
unfreed ref...

i can't find in your code where the free are not done....


-- 
Fabien Bodard




More information about the User mailing list