Chromium Chronicle #1: sprawdzone metody dotyczące planowania zadań

Zespół Chrome z dumą przedstawia Chromium Chronicle, miesięczną stworzonych z myślą o użytkownikach Chromium, przeglądarki.

Chromium Chronicle kładzie nacisk głównie na przekazywanie wiedzy technicznej oraz sprawdzone metody pisania, tworzenia i testowania Chrome. Planujemy udostępnić tematy, które są istotne i przydatne dla programistów Chromium (np. kod), zdrowie, przydatne narzędzia, testy jednostkowe, ułatwienia dostępu i nie tylko. Każdy artykuł będzie napisana i edytowana przez inżynierów Chrome.

Ta nowa seria bardzo się cieszy i mamy nadzieję, że Ty też! Wszystko gotowe? Obejrzyj pierwszy odcinek poniżej.

Sprawdzone metody dotyczące planowania zadań

Odcinek 1: Gabriel Charette, Montreal, PQ (kwiecień 2019 r.)
Poprzednie odcinki

Kod Chrome, który wymaga asynchronicznego wykonywania w trakcie procesu, zwykle publikuje zadania do sekwencji. Sekwencje to zarządzane przez Chrome „wątki wirtualne” i są wolisz utworzyć własny wątek. Jak obiekt i w której kolejności wysłać wiadomość?

Nie

Stary model polega na otrzymaniu od twórcy elementu SequencedTaskRunner:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
Tak

Preferowanym modelem jest utworzenie niezależnego elementu SequencedTaskRunner:

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

Są one łatwiejsze do czytania i pisania, ponieważ wszystkie informacje są dostępne lokalnie, nie istnieje ryzyko współdziałania z niepowiązanymi ze sobą zadaniami.

Taki model jest też lepszy w przypadku testowania. Zamiast wstrzykiwać uruchamiających zadania ręcznie, testy mogą inicjować kontrolowane środowisko zadań aby zarządzać zadaniami Foo:

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

Ustawienie TaskEnvironment na pierwszym planie w naturalny sposób zarządza środowiskiem zadań przez cały czas istnienia Foo. Środowisko zadań przechwytuje żądanie Foo w celu utworzenia obiektu SequencedTaskRunner, będzie zarządzać zadaniami w ramach każdego testu FooTest.

Aby sprawdzić wynik wykonania asynchronicznego, użyj Model RunLoop::Run()+QuitClosure():

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

Jest to lepsze rozwiązanie niż RunUntilIdle(), który może działać niestabilnie, jeśli funkcja asynchroniczna zadanie obejmuje zadanie spoza zakresu TaskEnvironment, np. jest zdarzeniem systemowym, więc używaj RunUntilIdle() z rozwagą.

Chcesz dowiedzieć się więcej? Zapoznaj się z dokumentacją dotyczącą podziału na wątki i zadań. lub weź udział w migracji do TaskEnvironment.