Это в контексте API параллелизма Microsoft C ++.
Есть класс под названием agent
(под Concurrency
пространство имен), и это в основном конечный автомат, который вы получаете и реализуете чисто виртуальный agent::run
,
Теперь вы обязаны позвонить agent::start
, который поместит его в работоспособный государство. Вы тогда звоните agent::wait
* или любой из его вариантов, чтобы фактически выполнить agent::run
метод.
Но почему мы должны позвонить agent::done
в теле? Я имею в виду, очевидный ответ заключается в том, что agent::wait
* будет ждать пока сигнал о готовности не истечет или не истечет время ожидания, но …
Что хотели дизайнеры? Почему бы не сделать так, чтобы агент перешел в состояние готовности? agent::run
возвращается? Это то, что я хочу знать. Почему у меня есть возможность не звонить done
? Методы ожидания генерируют исключения, если время ожидания истекло.
Единственная причина, по которой я вижу это то, что она позволяет вам заявить, что вы 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 */ }
};
… / пожимание плечами
Других решений пока нет …