Контрольный цикл закрытия Вала

#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);
            }
        );
    }
}