$this->this and avoiding circular references

php.internals

Alan Pinstein

20 years ago
Hi all- I've been trying to avoid circular references in some data import scripts and finally figured out how to do it. However, I wanted to ask you guys to make sure that what I'm doing is something that's legit and can be relied on into the future. Also, please note that I tried searching the archives for "this" and "this->this" but the searcher keeps removing "this" from my query! So sorry if this is asked and answered.... So, my objects are in a parent-child relationship and they both have links to each other... pretty standard circular reference scenario:
> ParentObject: > > function addChildObject($c) > { > $this->children[] = $c; > $c->setParent($this->this); // this syntax is the only way I > found to make "$this" not get refcounted here > } > > Now, to make this work as it should without incrementing the ref > counts when storing the link to the parent, setParent() needs to > have a non-refcounted pointer to the object: > > ChildObject: > > // need & in both places to make the ref not get ref-counted > function setParent(&$parent) > { > $this->-parent = &$parent; > }
My question is, is "$this->this" valid syntax? Can it be relied on? Is my overall approach sane? It's very important that I get memory management working in such a way here because the objects are used in large loops for importing data, and without this, the script uses unbounded amounts of memory. With this, it uses a finite amount of memory and works beautifully. Thanks in advance, Alan

Jochem Maas

20 years ago
are you using ph4 or php5? are you setting $this->this yourself or 'is it just there'? Alan Pinstein wrote:
> Hi all- > > I've been trying to avoid circular references in some data import > scripts and finally figured out how to do it. However, I wanted to ask > you guys to make sure that what I'm doing is something that's legit and > can be relied on into the future. > > Also, please note that I tried searching the archives for "this" and > "this->this" but the searcher keeps removing "this" from my query! So > sorry if this is asked and answered.... > > So, my objects are in a parent-child relationship and they both have > links to each other... pretty standard circular reference scenario: > > >> ParentObject: >> >> function addChildObject($c) >> { >> $this->children[] = $c; >> $c->setParent($this->this); // this syntax is the only way
assuming php4, I would say this these lines should be (difficult to tell though, without more insight/code/brains to play with ;-): function addChildObject(&$c) { $this->children[] =& $c; $c->setParent( $this ); }

Alan Pinstein

20 years ago
> are you using ph4 or php5?
PHP5
> are you setting $this->this yourself or 'is it just there'?
No, I'm not setting it, just reading it (see addChildObject() code below), if that's what you mean. -Alan

Antony Dovgal

20 years ago
On 07.12.2005 18:40, Alan Pinstein wrote:
> Hi all-
<skip> Please use php-general@lists.php.net for questions regarding development *in* PHP.
-- Wbr, Antony Dovgal

David Zülke

20 years ago
I don't think PHP-general would be of much help here. After all, his question was whether this behavior is intentional or not, and if it can be relied upon in the future. To me, it's an engine thing. And I'm interested in what the devs can say about this, too. - David Am 07.12.2005 um 17:27 schrieb Antony Dovgal:

Roman Ivanov

20 years ago
Antony Dovgal wrote:
> On 07.12.2005 18:40, Alan Pinstein wrote: > >> Hi all- > > <skip> > > Please use php-general@lists.php.net for questions regarding development > *in* PHP.
Please stop bashing other people's messages for the sole reason they do not deal with C code. The question was perfectly relevant.

Alan Pinstein

20 years ago
Well I posted there first, and someone helped me believe that & on objects does indeed legitimately not bump the refcount, but no one knows about $this->this. And there's another similar thread on the dev list anyway which was answered usefully: http:// aspn.activestate.com/ASPN/Mail/Message/php-Dev/1555640 Plus, this is kind of an *internals* question because the topic not documented publicly and it has to do with things that are opaque to userland like refcounts and how "$this" works. Alan On Dec 7, 2005, at 11:27 AM, Antony Dovgal wrote:

Alan Pinstein

20 years ago
My question is closely related to the one discussed on this php-dev thread: http://thread.gmane.org/gmane.comp.php.devel/32430 Someone just sent me this link, which I didn't find myself when searching b/c the searches strip "this" from queries. Anyway, the question is related to reference counting of objects when assigned by value and by reference. It is a very important OO topic as the ability to have a non-ref-counted object "handle" is basically requisite to prevent circular reference deadlocks in OO projects. If the way I have proposed doesn't work, then what is the official way? And there *must* be one, otherwise, there is no way to avoid huge memory leaks (deferred release until end-of-script, I know, but it's a memory leak in the context of the script while it's running) with this kind of OO arrangement. In particular what confuses me is, why does, at least on PHP 5.0.4, this: $obj = &$this->this; // doesn't seem to increment the refcount of the object behaves differently from: $obj = &$this; // does seem to increment the refcount to the object References to $this should not only be valid, but are pretty much required for proper memory management in an OO environment, unless there is some other sanctioned way to get a weak reference... now I am not sure if the fact that making a & reference to an object doesn't increment the refcount is intended behavior, or an unintended side effect that may change. This is one of my major questions. Also, in regards to the thread linked above, I'd say that making & $this an error is not desirable behavior; but maybe changing the value of $this should be (ie in C terms, $this is not an lvalue). Although, in C++/Obj-C you *can* even change this/self... in fact it's common in Obj-C: - (id) init { if (self = [super init]) { /* etc */ } return self; } Of course PHP is not Obj-C, but it's OO and garbage collected in a similar way, so PHP has the same need for manipulating $this; that is, creating weak references. Alan On Dec 7, 2005, at 11:27 AM, Antony Dovgal wrote:

Andi Gutmans

20 years ago
Hi Alan, Generally speaking, if you create a circular reference (whether by reference or by value), then you will have a "memory leak" until the end of the request. This is not only true for objects (and circular references might be indirect) but also for arrays. This is a side-effect of reference counting systems, but within the way PHP is used within a request/response paradigm, it shouldn't be a real limiting factor in real-life usage. On the contrary, for these kind of apps, garbage collecting systems have potential to be significantly slower. Andi At 08:15 PM 12/7/2005, Alan Pinstein wrote:

Alan Pinstein

20 years ago
> Generally speaking, if you create a circular reference (whether by > reference or by value), then you will have a "memory leak" until > the end of the request. This is not only true for objects (and > circular references might be indirect) but also for arrays.
sure, of course...
> This is a side-effect of reference counting systems, but within the > way PHP is used within a request/response paradigm, it shouldn't be > a real limiting factor in real-life usage.
Well I'd say that using a PHP-CLI script to import bulk data is a real-life usage and this is definitely a limiting factor. Do you disagree?
> On the contrary, for these kind of apps, garbage collecting systems > have potential to be significantly slower.
Well, Cocoa solves the problem in a manner I consider quite graceful. In 99% of situations, you don't touch memory management and things work themselves out like in PHP. However, there is a concept of a WEAK REFERENCE (a non-ref-counted ptr to the object) that is used *specifically* in these cases to prevent circular references. With this type of system, there is no additional overhead because the GC doesn't have to "detect" circular references and determine if the objects are orphaned but deadlocked... instead this is a situation left to the developer to manage. Now I understand that PHP isn't Obj-C and it's a higher-level language and that's fine. However, my question, which still remains unanswered, is that I've found a way that "seems" to create a weak reference and I'm simply asking if what I am doing is condoned or just lucky (and thus a bad idea that will probably break in the future)... And, if it's just lucky, then what is the solution to the problem? Am I just SOL? Is the answer simply that if you *need* to create circular references in PHP, then you *must* accept memory leakage? Alan

Robert Cummings

20 years ago
On Fri, 2005-12-09 at 00:21, Alan Pinstein wrote:
> > And, if it's just lucky, then what is the solution to the problem? Am > I just SOL? Is the answer simply that if you *need* to create > circular references in PHP, then you *must* accept memory leakage?
If you know you have a circular reference you can always use unset() to break the reference and thus break the circle. Cheers, Rob.
-- .------------------------------------------------------------. | InterJinn Application Framework - http://www.interjinn.com | :------------------------------------------------------------: | An application and templating framework for PHP. Boasting | | a powerful, scalable system for accessing system services | | such as forms, properties, sessions, and caches. InterJinn | | also provides an extremely flexible architecture for | | creating re-usable components quickly and easily. | `------------------------------------------------------------'

Wez Furlong

20 years ago
On 12/9/05, Alan Pinstein <apinstein@mac.com> wrote:
> However, my question, which still remains unanswered, is that I've > found a way that "seems" to create a weak reference and I'm simply > asking if what I am doing is condoned or just lucky (and thus a bad > idea that will probably break in the future)...
The general rule of thumb is that if what you're doing makes you feel dirty inside, or feels wrong, or that it might not work in the future, then you shouldn't rely on it working that way. I'm not saying that this hack is or is not planned to go away, but there is a real possibility that it might go away as the side-effect of some other change. So, if it works for you, that's fine... but if you're writing something that you want to be used successfully with future PHP versions, then you should avoid using it.
> And, if it's just lucky, then what is the solution to the problem? Am > I just SOL? Is the answer simply that if you *need* to create > circular references in PHP, then you *must* accept memory leakage?
While I love the idea of writing everything in PHP, if you find yourself up against a limitation that you can't avoid without nasty hacks, then perhaps PHP is the wrong tool for that particular job. --Wez.

Jochem Maas

20 years ago
Andi - your email client seems to be leaking :-) Andi Gutmans wrote:

Andi Gutmans

20 years ago
Sorry about that. I think it might be a problem with the server not my client. If it persists please let me know. At 08:37 AM 12/9/2005, Jochem Maas wrote:

Jochem Maas

20 years ago
Andi Gutmans wrote:
> Sorry about that. I think it might be a problem with the server not my > client. > If it persists please let me know.
given what your work has done for me I can't consider it a problem :-) just thought it was kinda funny. regarding the actually topic of this thread I'm very interested in the concept of 'weak references' (as Apple seems to call them), what '$this->this' is all about, and whether using reference notation with object variable assignment is even allowed, whether it it makes a difference and what the future holds with regard to being able to use/create references to object 'handles'. I remember someone else asking on this list about the ability/possiblity of being able to make the distinction between object 'handles' and references to object 'handles' - I can't remember anythnig conclusive coming out of the discussion. regardless I feel that Alan did make some valid points in this area, given that the core/dev team may think that Alan's app (in this case) would be better off being refactored it might be an idea for some documentation to be created that gives an indication on how to overcome these percieved referencing problems (i.e. some strategies on how to design something that does work with in the confines of php's capabilities) for the record I have an OO based import script that imports about 13 files, one of which has 500,000 lines of data, and I see that the memory usage of my script grows and grows (upto about 100Mb) - I figure it could do it alot more efficiently, having some ammunition regarding how to tackle such an issue (in general terms) would be a great benefit - given the generic nature of the problem I believe many more developers could benefit. kind rgds, Jochem

Alan Pinstein

20 years ago
> regarding the actually topic of this thread I'm very interested > in the concept of 'weak references' (as Apple seems to call them), > what '$this->this' is all about, and whether using reference notation > with object variable assignment is even allowed, whether it it makes > a difference and what the future holds with regard to being able to > use/create references to object 'handles'.
Yes, back to the thread :) So a colleague on the propel-dev list has convinced me that my approach is bad, mostly because of how references behave in PHP. While doing my "research" I stumbled on to the fact that making references doesn't bump refcounts, and got so excited by the potential "solution" to my problem that I forgot about the flip-side of using references, which is that it binds the reference to the same place as the original. Thus, when the original changes, it changes the target of your "stored link". So my solution in the end won't work at all. However, the need is definitely still there. Andi briefly mentioned an alternative solution, and I am eagerly awaiting his complete response... c'mon with it Andi! Another poster recommended that maybe PHP isn't the right "tool" for the job [of importing data]. This would imply that PHP is for your web pages, but no other part of your application. Well, if I am starting out on a new project, I'd like for the entire project to be in one language. I want to be able to have all of my business logic for my application's model in one place, and be able to use this core model from the web, scripts, etc. This poster's comment would indicate that PHP's stated purpose is as a web tool only, and isn't intended as a project (now or in the future) to be a universal solution to building applications. If this is the case, I'd consider it a shame, and it would have me seriously reconsider using PHP long term. A mindset like this is why there is such anti-php sentiment from the ruby and python people. Whether you like it or not, PHP has become a complete language platform. I like the PHP paradigm overall, but need to be able to have projects entirely in PHP for it to be worthwhile to use. If I have to develop my core model in Java [or whatever], I am not sure that I would use PHP to do the front-end. Although, on a side note, I did recently use the excellent php-java- bridge to build a PHP front-end to a Java search engine, and it works very well. Not sure yet about performance, though. Alan

David Zülke

20 years ago
Would you mind explaining that "indirect property accessing" method, Andi? Or did you mean avoiding circular references altogether by having a third "intermediate" layer that would return the respective object when handed a GUID or something, so that effectively, one of the partners in the circle doesn't store the other partner directly, but just a unique identifier usind which you can retrieve it? (that's the way you have to do it in JavaScript if you don't want IE to crash due to memleaks when referencing from DOM elements to JS objects and vice versa) Thanks, - David Am 09.12.2005 um 18:08 schrieb Andi Gutmans: