Chromium Chronicle #25: Chú thích an toàn cho chuỗi

Tập 25: của Victor Costan tại SFO (tháng 10 năm 2021)
Các tập trước

Trong C++, việc loại trừ khả năng chạy đua dữ liệu đòi hỏi bằng chứng nhỏ về tính chính xác của luồng (thread) an toàn cho mọi quyền truy cập của thành viên dữ liệu. Những minh chứng này khiến bạn gặp rất nhiều công sức, đặc biệt là khi xem xét hoặc tái cấu trúc mã. Khung phân tích tĩnh của Clang đảm nhận phần công việc khó khăn cho việc kiểm tra độ an toàn của luồng.

Thêm GUARDED_BY_CONTEXT() vào các thành phần dữ liệu trong các lớp không an toàn của luồng

Hầu hết các lớp Chrome đều không an toàn cho luồng và bạn nên sử dụng trên một trình tự. Thêm chú giải cho tất cả thành phần dữ liệu không an toàn cho luồng. Các chú giải không cần thiết vẫn an toàn, nhưng việc thiếu chú thích có nguy cơ xảy ra tình huống tranh chấp dữ liệu.

#include "base/sequence_checker.h"  // for SEQUENCE_CHECKER()
#include "base/thread_annotations.h"  // for GUARDED_BY_CONTEXT()

class Cache {
  // Methods here.
 private:
  SEQUENCE_CHECKER(sequence_checker_);
  base::flat_map<std::string, std::string> data_ GUARDED_BY_CONTEXT(sequence_checker_);
};

Clang thực thi các bước kiểm tra trình tự

Đổi lại, sau khi chú thích các thành phần dữ liệu, Clang đảm bảo rằng mọi phương thức truy cập vào dữ liệu đều thực hiện quy trình kiểm tra an toàn trình tự trước khi làm như vậy. Khi mã được di chuyển xung quanh trong quá trình tái cấu trúc, Clang tiếp tục thực thi chú thích GUARDED_BY_CONTEXT().

void Cache::Set(base::StringPiece key, base::StringPiece value) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);  // Clang warns without this.
  data_.emplace(key, value);
}

Thêm GUARDED_BY() vào các thành phần dữ liệu trong các lớp an toàn cho luồng sử dụng mutex

Một số lớp trong Chrome phải sử dụng khoá để đảm bảo an toàn cho luồng. Trong những trường hợp này, hãy chú thích tất cả các thành phần dữ liệu không an toàn cho luồng. Mỗi chú giải trỏ đến một mutex phải được giữ khi truy cập vào thành phần dữ liệu.

#include "base/thread_annotations.h"  // for GUARDED_BY()

class ThreadSafeCache {
  // Methods here.
  private:
    base::Lock lock_;
    base::flat_map<std::string, std::string> data_ GUARDED_BY(lock_);
};

Clang thực thi việc thu nạp khoá

Hãy đợi và để trình biên dịch đảm bảo rằng mỗi base::AutoLock đều được xác định phạm vi chính xác, và khoá cuộc gọi Acquire()Release() được ghép nối đúng cách.

void ThreadSafeCache::Set(base::StringPiece key, base::StringPiece value) {
  base::AutoLock auto_lock(lock_);  // Clang warns without this.
  data_.emplace(key, value);
}