Понимание stateful_actor

Я читал об использовании stateful_actor в примерах /curl/curl_fuse.cpp и libcaf_core/test/stateful_actor.cpp. Похоже, что stateful_actor<State> может привязать некоторые состояния для актера, объявив поля в State struct. Это очень полезно.

Можем ли мы объявить состояния как поля в class-based actor, чтобы получить тот же эффект? Или в stateful_actor есть какая-то особая обработка (например, доступ к потокобезопасности)?

Предоставляют ли актеры в следующем примере одинаковую функциональность?

/* Class based actor */
struct ClassCounter : caf::event_based_actor
{
    caf::behavior make_behavior() override { 
        return { 
            [=](inc_atom){ i += 1; }
          , [=](ret_atom){ return i; }
        };
    }

    const char* name() const override { return "I am class-based"; }
    int i = 0;
};

/* Stateful actor */
struct CounterState
{
    caf::local_actor* self;
    int i = 0;
    const char* name = "I am stateful";
};

caf::behavior StatefulCounter(caf::stateful_actor<CounterState>* self)
{
    return {
        [=](inc_atom){ self->state.i += 1; }
      , [=](ret_atom){ return self->state.i; }
    };
};

person Chen OT    schedule 21.12.2015    source источник


Ответы (1)


Можем ли мы объявить состояния как поля в class-based actor, чтобы получить тот же эффект? Или в stateful_actor есть какая-то особая обработка (например, доступ к потокобезопасности)?

Среда выполнения CAF предполагает, что акторы изолированы, т. е. только самому актору разрешен доступ к его состоянию. Следовательно, доступ к состоянию актора никогда не синхронизируется. В межакторном общении используется передача сообщений, что позволяет избежать условий гонки по замыслу.

Субъекты с состоянием позволяют программистам писать меньше классов (и, следовательно, меньше шаблонного кода), но есть также одно заметное различие между ClassCounter и StatefulCounter: время жизни переменных. В ClassCounter переменная-член i существует до тех пор, пока не будет вызван деструктор ClassCounter. Поскольку акторы подсчитываются по ссылкам, деструктор запускается, если на него не осталось ссылок, т. е. не существует дескриптора actor или actor_addr для актора. В StatefulCounter член CounterState создается, если актор инициализируется, и уничтожается, если он завершается.

Государство существует только до тех пор, пока жив актер. Это особенно полезно для прерывания циклов. Если у вас есть два актора A и B, у вас есть цикл, если A содержит ссылку на B через переменную-член, и наоборот. Вместо этого использование акторов с состоянием разрывает этот цикл. A автоматически освобождает свою ссылку на B при выходе и наоборот.

person neverlord    schedule 21.12.2015
comment
Значит, деструктор CounterState будет вызываться, когда актор завершает работу? - person Chen OT; 22.12.2015
comment
мм. Я думаю, что разделение проблем поведения государства и актора лучше для обслуживания. - person Chen OT; 22.12.2015
comment
Значит, деструктор CounterState будет вызываться, когда актор завершает работу? Да. Актер закрывает свой почтовый ящик и уничтожает свое состояние при завершении. При необходимости он также будет вызывать сообщения о выходе или отключении. Любое дальнейшее входящее сообщение будет отброшено (инициируя сообщение об ошибке для сообщений синхронизации), а связывание с завершенным субъектом немедленно вызовет сообщение о выходе. - person neverlord; 22.12.2015