The Chromium Chronicle n. 1: best practice per la pianificazione delle attività

Il team di Chrome è orgoglioso di presentare Chromium Chronicle, un servizio mensile pensata appositamente per gli sviluppatori di Chromium, che creano del browser.

Il Chronicle di Chromium si concentrerà principalmente sulla diffusione delle conoscenze tecniche e best practice per scrivere, creare e testare Chrome. Il nostro obiettivo è includere argomenti pertinenti e utili per gli sviluppatori di Chromium, ad esempio codice salute, strumenti utili, test delle unità, accessibilità e molto altro ancora. Ogni articolo verranno scritti e modificati dagli ingegneri di Chrome.

Siamo entusiasti di questa nuova serie e ci auguriamo che lo sia anche tu. Vuoi iniziare? Dai un'occhiata al nostro primo episodio qui sotto.

Best practice per la pianificazione delle attività

Episodio 1: di Gabriel Charette a Montréal, PQ (aprile 2019)
Puntate precedenti

Il codice di Chrome che richiede l'esecuzione asincrona nei processi di solito pubblica le attività alle sequenze. Le sequenze sono "thread virtuali" gestiti da Chrome e sono preferito per creare il tuo thread. In che modo un oggetto in quale sequenza pubblicare?

Cosa non fare

Il vecchio paradigma consiste nel ricevere un SequencedTaskRunner dal creatore:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
Cosa fare

Il paradigma preferito è creare un oggetto SequencedTaskRunner indipendente:

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

Questo è più facile da leggere e scrivere perché tutte le informazioni sono locali e nessun rischio di interdipendenza con attività non correlate.

Questo paradigma è migliore anche quando si tratta di test. Invece di iniettare manualmente gli utenti che eseguono le attività, i test possono verificare un ambiente di attività controllato per gestire le attività di Foo:

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

Avere TaskEnvironment per primo nell'impianto garantisce che e gestisce l'ambiente delle attività per tutta la vita di Foo. TaskEnvironment acquisirà la richiesta alla costruzione di Foo per creare un SequencedTaskRunner e ne gestirà le attività in ogni FooTest.

Per verificare il risultato dell'esecuzione asincrona, utilizza il metodo Paradigma RunLoop::Run()+QuitClosure():

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

È preferibile usare RunUntilIdle(), che può essere instabile se lo stato il carico di lavoro coinvolge un'attività che non rientra nell'ambito di TaskEnvironment, ad es. un evento di sistema, quindi usa RunUntilIdle() con attenzione.

Ti piacerebbe saperne di più? Leggi la nostra documentazione su threading e attività o partecipa alla migrazione in TaskEnvironment.