Chronicle 1 של Chromium: שיטות מומלצות לתזמון משימות

צוות Chrome גאה להציג את Chromium Chronicle, סדרה חודשית שנועדה במיוחד למפתחי Chromium, מפתחים שבונים את הדפדפן.

Chromium Chronicle יתמקד בעיקר בהפצת ידע טכני ושיטות מומלצות לכתיבה, לבנייה ולבדיקה של Chrome. התוכנית שלנו היא להציג נושאים שרלוונטיים ושימושיים למפתחי Chromium, כמו תקינות הקוד, כלים שימושיים, בדיקת יחידות, נגישות ועוד הרבה יותר! כל מאמר ייכתב ויערוך על ידי מהנדסי Chrome.

אנחנו נרגשים לגבי הסדרה החדשה הזו, ומקווים שגם אתם! מוכנים להתחיל? כדאי לצפות בפרק הראשון שלנו בהמשך.

שיטות מומלצות לתזמון משימות

פרק 1: מאת גבריאל צ'ארט במונטריאול, מקסיקו (PQ (אפריל 2019)
הפרקים הקודמים

קוד Chrome הדורש הפעלה אסינכרונית בתוך תהליך מפרסם בדרך כלל משימות ברצפים. רצפים הם 'שרשורים וירטואליים' שמנוהלים על ידי Chrome, ומומלץ ליצור שרשורים משלכם. איך אובייקט יכול לדעת לאיזה רצף לפרסם אותו?

מה אסור לעשות

הפרדיגמה הישנה היא לקבל SequencedTaskRunner מהיוצר:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
מה מותר לעשות

הפרדיגמה המועדפת היא יצירת SequencedTaskRunner עצמאי:

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

קל יותר לקרוא ולכתוב את המידע הזה, כי כל המידע הוא מקומי ואין סיכון של תלות הדדית במשימות שאינן קשורות.

פרדיגמה זו טובה יותר גם כשמדובר בבדיקה. במקום להחדיר משימות להריץ משימות באופן ידני, תוכלו ליצור סביבת משימות מבוקרת שתנהל את המשימות של Foo:

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

אם TaskEnvironment קודם במתקן, היא מבטיחה באופן טבעי שסביבת המשימה תנהל את סביבת המשימה לכל משך החיים של Foo. סביבה של Tasks תתעד את הבקשה של Foo כדי ליצור SequencedTaskRunner, ותנהל את המשימות שלה בכל בדיקת FooTest.

כדי לבדוק את התוצאה של הביצוע האסינכרוני, משתמשים בפרדיגמה RunLoop::Run()+QuitClosure():

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

זו אפשרות מועדפת ל-RunעדIdle(), שיכולה להיות לא יציבה אם עומס העבודה האסינכרוני כרוך במשימה שאינה בטווח המשימה של TaskEnvironment, למשל אירוע מערכת, לכן כדאי להשתמש ב-RunUntilIdle().

רוצים עוד פרטים? כדאי לקרוא את התיעוד שלנו בנושא חלוקה ל-threads ומשימות, או לקחת חלק במיגרציה ל-taskEnvironment!