Chromium Chronicle n°1: bonnes pratiques de planification des tâches

L'équipe Chrome est fière de vous présenter Chromium Chronicle, un rapport mensuel s'adressant spécifiquement aux développeurs Chromium, aux développeurs navigateur.

Chromium Chronicle se concentrera principalement sur la diffusion des connaissances techniques et les bonnes pratiques pour écrire, compiler et tester Chrome. Notre objectif est de présenter les sujets pertinents et utiles pour les développeurs Chromium, tels que le code santé, outils utiles, tests unitaires, accessibilité et bien plus encore ! Chaque article seront écrites et modifiées par les ingénieurs de Chrome.

Nous sommes ravis de cette nouvelle série, et nous espérons que vous l'êtes aussi ! Vous êtes prêt à vous lancer ? Découvrez notre premier épisode ci-dessous.

Bonnes pratiques de planification des tâches

Épisode 1:par Gabriel Charette à Montréal, PQ (avril 2019)
Épisodes précédents

Le code Chrome nécessitant une exécution asynchrone en cours de processus publie généralement des tâches aux séquences. Les séquences sont des "threads virtuels" gérés par Chrome et sont plutôt que de créer votre propre fil de discussion. Comment un objet sur quelle séquence publier ?

À éviter

L'ancien paradigme consiste à recevoir un SequencedTaskRunner de la part du créateur:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
À faire

Il est recommandé de créer un SequencedTaskRunner indépendant:

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

C'est plus facile à lire et à écrire car toutes les informations sont locales et il y a aucun risque d'interdépendance avec des tâches sans rapport.

Ce paradigme est également préférable pour les tests. Au lieu d’injecter manuellement les exécuteurs de tâches, les tests peuvent instancier un environnement de tâches contrôlé. pour gérer ses tâches:

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

Le fait d'avoir TaskEnvironment en premier dans l'équipement garantit naturellement gère l'environnement des tâches tout au long de sa vie. TaskEnvironment capturera la requête de Foo lors de la construction pour créer un SequencedTaskRunner et gérera ses tâches sous chaque FooTest.

Pour tester le résultat de l'exécution asynchrone, utilisez la méthode Paradigme RunLoop::Run()+QuitClosure():

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

Cette méthode est privilégiée par rapport à RunJusqu'Idle(), qui peut être instable si la méthode charge de travail implique une tâche en dehors de la vue d'ensemble de TaskEnvironment, Ex. : un événement système. Vous devez donc utiliser RunUntilIdle() avec précaution.

Envie d'en savoir plus ? Consultez notre documentation sur l'exécution de threads et les tâches. ou participer à la migration vers TaskEnvironment !