#glib #vala #gobject #reference-cycle
#бойкий #вала #объект #ссылочный цикл
Вопрос:
Я пишу класс в Vala, в котором я связываю два свойства одного и того же объекта вместе с замыканием для преобразования одного в другое.
class Foo : Object
{
public int num { get; set; }
public int scale = 2;
public int result { get; set; }
construct {
this.bind_property("num", this, "result", 0,
(binding, src, ref dst) => {
var a = src.get_int();
var b = this.scale;
var c = a * b;
dst.set_int(c);
}
);
}
}
Закрытие сохраняет ссылку this
(потому что я использую this.scale
), которая создает цикл ссылок, который поддерживает мой класс в рабочем состоянии, даже когда все остальные ссылки на него потеряны.
Привязка будет удалена только тогда, когда количество ссылок достигнет 0, но refcount достигнет 0 только тогда, когда ожидание и его закрытие будут удалены.
Есть ли способ сделать ссылку закрытия на this
слабой? Или проверить, когда значение refcount достигнет 1, чтобы удалить его?
Ответ №1:
Не проверено, но можете ли вы присвоить this
слабой переменной и вместо этого ссылаться на нее в закрытии? Например.:
weak Foo weak_this = this;
this.bind_property(…, (…) => {
…
b = weak_this.scale;
…
}
Комментарии:
1. Спасибо за совет. К сожалению, после проверки сгенерированного кода Vala, похоже, сохраняет сильную ссылку на
this
, даже если она нигде не используется :-
Ответ №2:
Это известный недостаток компилятора Vala, который обсуждается в этом выпуске.
На данный момент проблемы можно избежать, выполнив привязку из статического метода, в котором закрытие не фиксируется this
.
class Foo : Object
{
public int num { get; set; }
public int scale = 2;
public int result { get; set; }
construct {
this.bind_properties(this);
}
private static void bind_properties(Foo this_)
{
weak Foo weak_this = this_;
this_.bind_property("num", this_, "result", 0,
(binding, src, ref dst) => {
var a = src.get_int();
var b = weak_this.scale;
var c = a * b;
dst.set_int(c);
}
);
}
}