PHP, немедленная сборка мусора с помощью слабых ссылок вызывает ошибкуPhp

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 PHP, немедленная сборка мусора с помощью слабых ссылок вызывает ошибку

Сообщение Anonymous »

У меня есть большая объектная структура, которая, конечно же, имеет множество ссылок на другие объекты. У меня есть много отношений один-ко-многим между этими объектами. Так, например: пользователи моего класса содержат массив свойств $users, который содержит дочерние элементы класса user, чье свойство пользователей $container ссылается обратно на "содержащий" класс.
Если два объекта ссылаются друг на друга, они никогда не будут подвергаться сборке мусора, поскольку всегда будут ссылки на оба. Поэтому я использую слабые ссылки для ссылок на контейнеры. Я создал черту, которая отлично с этим справляется и работает уже много лет.
В конструкторе я могу сделать это:

Код: Выделить всё

class user {
use weakObjReference;
function __construct(users $container) {
$this->weakReference($container, 'container');
// can use $this->container now everywhere; the trait has stored it internally as a WeakReference
// and via __get gives it back as a normal (strong) object reference
}
}
Это работает! Ни один объект не хранится вечно.
Однако у меня иногда возникают проблемы, когда я создаю экземпляры на лету. Самый простой пример:

Код: Выделить всё

class a  {
public readonly b $b;

function __construct(public string $name) {
$this->b = new b($this);
}

function hoohoo(): mixed {
return $this->b;
}
}

class b  {

use weakObjReference;

function __construct(a $container) {
$this->weakReference($container, 'container');  // $this->container "created"
}

function heehee($name): mixed {
$x = $name . ', '. $this->container->name;
return $x;

}
}

$a = new a('world 1');
var_dump($a->hoohoo()->heehee('hello'));  // EXAMPLE 1
var_dump((new a('world 2'))->hoohoo()->heehee('good afternoon'));  // EXAMPLE 2.
https://3v4l.org/7DpN2
ПРИМЕР 1. РАБОТАЕТ. Возвращает «привет, мир 1».
ПРИМЕР 2. ОШИБКА. слабыйObjReferenceStorage::get(): Возвращаемое значение должно иметь тип объекта, возвращаемое значение NULL, другими словами: слабая ссылка недействительна, поскольку экземпляр был удален.
Это означает, что сбор мусора слишком агрессивен для моих целей. Как только heehee() выполняется, экземпляр класса a уже уничтожается, поэтому WeakReference обратно в a больше не работает. Я думал, что сбор мусора будет производиться после утверждения, но видимо сильно ошибаюсь; это делается немедленно, пока оператор еще выполняется.
Я принял некрасивое решение, снова временно сделав экземпляры сильными. Но это неустойчиво для всей системы со многими классами, поскольку требует точного знания, когда сделать ссылку временно сильной, а когда снова слабой для нескольких классов. Чтобы увидеть, насколько это беспорядочно, я добавил уровень контейнеров:

Код: Выделить всё

class a  {
public readonly b $b;

function __construct(public string $name) {
$this->b = new b($this);
}

function hoohoo(): mixed {
$this->b->temporaryStrong('container');
return $this->b;
}
}

class b  {
public readonly c $c;

use weakObjReference;

function __construct(a $container) {
$this->weakReference($container, 'container');  // $this->container "created"
$this->c = new c($this);
}

function heehee(): mixed {
return $this->c;
}
}

class c  {

use weakObjReference;

function __construct(b $container) {
$this->weakReference($container, 'container');  // $this->container "created"
}

function haahaa($name): mixed {
$x = $name . ', '. $this->container->container->name;
$this->container->weakAgain('container');
return $x;

}
}

$a = new a('world 1');
var_dump($a->hoohoo()->heehee()->haahaa('hello'));  // EXAMPLE 1
var_dump((new a('world 2'))->hoohoo()->heehee()->haahaa('good afternoon'));  // EXAMPLE 2.
https://onlinephp.io/c/61a46
Это работает, но очевидно, что это не практическое/структурное решение с ->temporaryStrong () и ->weakAgain() разбросаны по всей системе.
Это кажется нишевой ситуацией, поскольку она возникает только тогда, когда вы создаете экземпляр на муха. Однако в моем случае это довольно стандартно (заводское). И еще с несколькими разными классами.
Как я могу решить эту проблему изящно, не заставляя использовать переменную в пользовательской области?

Подробнее здесь: https://stackoverflow.com/questions/791 ... uses-error
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»