Почему у меня есть возможность * не * вызывать Concurrency::agent::done внутри run?

Это в контексте API параллелизма Microsoft C++.

Есть класс под названием agent (под Concurrency пространство имен), и это в основном конечный автомат, который вы получаете и реализуете чисто виртуальный agent::run,

Теперь вы обязаны позвонить agent::start, который переведет его в работоспособное состояние. Вы тогда звоните agent::wait* или любой из его вариантов, чтобы фактически выполнить agent::run метод.

Но почему мы должны позвонить agent::done в теле? Я имею в виду, очевидный ответ заключается в том, что agent::wait* будет ждать пока сигнал о готовности не истечет или не истечет время ожидания, но...

Что хотели дизайнеры? Почему бы не сделать так, чтобы агент вошел в состояние готовности agent::run возвращается? Это то, что я хочу знать. Почему у меня есть возможность не звонить done? Методы ожидания генерируют исключения, если истекло время ожидания.

1 ответ

Решение

Единственная причина, по которой я вижу, состоит в том, что это позволит вам заявить, что вы done()затем проделайте дополнительную работу (скажем, очистку), которую вы не хотите ждать от своего потребителя.

Теперь они могли бы сделать это:

private: void agent::do_run() {
  run();
  if (status() != agent_done)
    done();
}

тогда есть их каркасный вызов do_run() вместо run() напрямую (или эквивалент).

Тем не менее, вы заметите, что вы сами можете сделать это.

class myagent: public agent {
protected:
  virtual void run() final override { /* see do_run above, except call do_run in it */ }
  virtual void do_run() = 0;
};

и пуф, если ваш do_run() не может позвонить done()функция обертывания делает это за вас. Если эта вторая виртуальная функция слишком высока для вас:

template<typename T>
class myagent: public agent {
private:
  void call_do_run()
  {
    static_cast<T*>(this)->do_run();
  }
protected:

  virtual void run() final override { /* see do_run above, but call_do_run() */ }
};

CRTP, который позволяет вам делать отправку во время компиляции. Использование:

class foo: public myagent<foo>
{
public:
  void do_run() { /* code */ }
};

... / пожимает плечами

Другие вопросы по тегам