Chromium Chronicle no 1: práticas recomendadas para programação de tarefas

A equipe do Chrome tem o prazer de apresentar o Chromium Chronicle, um voltada especificamente para os desenvolvedores do Chromium, aqueles que criam a navegador.

O Chromium Chronicle terá como foco principal a disseminação de conhecimento técnico e práticas recomendadas para escrever, criar e testar o Chrome. Nosso plano é apresentar tópicos que são relevantes e úteis para desenvolvedores do Chromium, como códigos integridade, ferramentas úteis, testes de unidade, acessibilidade e muito mais! Cada artigo serão escritos e editados pelos engenheiros do Chrome.

Estamos muito animados com a nova série e esperamos que você também esteja! Vamos nessa? Confira nosso primeiro episódio abaixo.

Práticas recomendadas para o agendamento de tarefas

Episódio 1:por Gabriel Charette em Montreal, PQ (abril de 2019)
Episódios anteriores

O código do Chrome que precisa de execução assíncrona no processo normalmente publica tarefas a sequências. Sequências são "linhas de execução virtuais" gerenciadas pelo Chrome e são preferem criar sua própria conversa. Como um objeto sabe em qual sequência postar?

O que não fazer

O paradigma antigo é receber um SequencedTaskRunner do criador:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
O que fazer

O paradigma preferido é criar um SequencedTaskRunner independente:

Foo::Foo()
    : backend_task_runner_(
          base::CreateSequencedTaskRunnerWithTraits({
              base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}

Isso é mais fácil de ler e escrever, pois todas as informações são locais e há sem risco de interdependência com tarefas não relacionadas.

Esse paradigma também é melhor quando se trata de testes. Em vez de injetar entre executores de tarefas manualmente, os testes podem instanciar um ambiente de tarefas controlado para gerenciar as tarefas do Foo:

class FooTest : public testing::Test {
 public
  (...)
 protected:
  base::test::TaskEnvironment task_environment_;
  Foo foo_;
};

Ter o TaskEnvironment primeiro no suporte garante naturalmente que ele gerencia o ambiente de tarefas durante todo o ciclo de vida do Foo. O TaskEnvironment vai capturar a solicitação na construção de Foo para criar um SequencedTaskRunner e vai gerenciar as tarefas em cada FooTest.

Para testar o resultado da execução assíncrona, use o Paradigma RunLoop::Run()+QuitClosure():

TEST_F(FooTest, TestAsyncWork) {
  RunLoop run_loop;
  foo_.BeginAsyncWork(run_loop.QuitClosure());
  run_loop.Run();
  EXPECT_TRUE(foo_.work_done());
}

É preferível usar RunUntilIdle(), que pode ser instável se o método assíncrono de trabalho envolve uma tarefa fora do âmbito do TaskEnvironment, Por exemplo: um evento do sistema. Portanto, use RunUntilIdle() com cuidado.

Quer saber mais? Leia nossa documentação sobre linhas de execução e tarefas ou participe da migração para o TaskEnvironment.