Opened 14 years ago

Closed 14 years ago

#3405 closed defect (fixed)

PHP/MapScript circular references between objects

Reported by: aboudreault Owned by: aboudreault
Priority: normal Milestone: 6.0 release
Component: MapServer C Library Version: svn-trunk (development)
Severity: normal Keywords: php, object reference
Cc:

Description

Currently, PHP/MapScript has circular references between objects that prevent the zend engine 2 garbage collector to delete objects when it should. In MapScript, most objects are a member/property of another object, excepted the map object. Also, most child objects need a reference to its parent for a some operations.

What is needed here is a way to keep the references count right between parent/child. A parent object cannot be deleted if a reference to one of its children is still available in the script, and vice-versa. And if the user frees this child reference, the parent and the child have to be deleted immediately.

Change History (2)

comment:1 by aboudreault, 14 years ago

As a first step, I tried to implement a lazy init system. The idea was to not create all object properties in the parent constructor but only to create them when the user needs them. That way, only the children would have a reference to the parent and have to deal with the zend garbage collector. The parent would only have an internal pointer to the child to know if it has to create a new php wrapper around the C internal object of to simply return a zval ref when the user request it.

Unfortunately, there is an important performance issue with this solution. The children are freed by the garbage collector *as soon as* there is no more references to them in the php script. Let's take this code:

$map = new mapObj(...);

echo $map->extent->minx." - ".$map->extent->miny." - ".$map->extent->maxx." - ".$map->extent->maxy;

In this case, 4 rect objects representing the same internal C object are create and freed immediately. This solution is not acceptable. I'll try to find a way to keep the lazy init system (because it can't be really useful) but to keep the object created internally without affecting the garbage collector work.

comment:2 by aboudreault, 14 years ago

Resolution: fixed
Status: newclosed

After a few other tries, it would have been possible to use the new php 5.3 garbage collection algorithm to collect the cycles between objects, but since php 5.2 is still largely used I opted to implement a free() method in each object that needs it. Now, resources can be totally freed during the script execution by the user. The lazy system init has been kept.

Fixed and committed in r10174 and documentation updated in r10184.

Note: See TracTickets for help on using tickets.