无标题
Quản lý và Mở/Khóa Tài Nguyên
Quản lý và Mở/Khóa tài nguyên
Quản lý và Mở/Khóa tài nguyên
Quản lý và kiểm soát tài nguyên Vào cuối tuần, chúng tôi gặp phải một vấn đề đặc biệt. Các tài nguyên đang chạy cần được quản lý tập trung, và bản thân tài nguyên được quản lý thông qua cơ chế thu gom rác (GC). Tuy nhiên, trong một số trường hợp, tài nguyên cần được khóa (lock) để đảm bảo không bị dọn dẹp khi xảy ra GC. Ban đầu, chúng tôi dự định sẽ treo các tài nguyên đang được khóa vào một chuỗi liên kết đặc biệt khi thực hiện lock, và gỡ chúng ra khi unlock.
Tuy nhiên, vấn đề phát sinh do tính chất tái sử dụng cao của tài nguyên. Vì không có cơ chế đếm tham chiếu, các thao tác unlock không thể hoạt động chính xác. Giải pháp hiển nhiên nhất là bổ sung đếm tham chiếu cho đối tượng, nhưng trực giác mách bảo phải có cách nào đó để tránh điều này. Việc sử dụng GC chính là để loại bỏ quy trình tăng/giảm tham chiếu thủ công phiền phức. Ngoài ra, chúng tôi sẽ phải thêm các phương thức kiểm soát tham chiếu vào giao diện tài nguyên - điều không khả thi vì thiết kế hiện tại không yêu cầu lớp cơ sở phải có các phương thức này. Hơn nữa, không phải đối tượng nào cũng cần lưu trữ biến đếm tham chiếu. Nếu đặt đếm tham chiếu bên ngoài đối tượng, chỉ có thể đặt trong nút của danh sách liên kết, nhưng lại cần cơ chế ánh xạ từ đối tượng tài nguyên sang nút liên kết tương ứng. Việc sử dụng map để thực hiện ánh xạ này rõ ràng là giải pháp tốn kém và thiếu hiệu quả.
Giải pháp cuối cùng chúng tôi áp dụng như sau: Sử dụng một mảng con trỏ để lưu trữ các địa chỉ tài nguyên. Mỗi khi thực hiện lock/unlock tài nguyên, chúng tôi trực tiếp đẩy địa chỉ của đối tượng vào mảng. Để phân biệt thao tác lock và unlock, chúng tôi áp dụng một kỹ thuật thông minh: khi unlock, địa chỉ sẽ được tăng thêm 1. Điều này khả thi nhờ đặc tính căn chỉnh địa chỉ theo DWORD (4 byte) của hầu hết các hệ thống.
Bằng cách đếm số lần lock/unlock, chúng tôi xác định chính xác số lượng tài nguyên đang bị khóa. Khi số lần unlock bằng số lần lock, mảng sẽ được làm sạch hoàn toàn. Trong thực tế, chúng tôi thường xuyên gọi phương thức unlock_all để xóa toàn bộ (thường thực hiện sau khi hoàn tất render một khung hình).
Khi phát hiện mảng chứa quá nhiều dữ liệu dư thừa (kích thước mảng lớn hơn nhiều so với số tài nguyên thực tế đang bị khóa), chúng tôi sẽ thực hiện tối ưu bằng cách sắp xếp mảng và quét một lượt để gộp các thao tác lock/unlock trùng lặp. Quy trình này được kích hoạt rất ít, đồng thời có thể hoàn thành nhanh chóng nhờ thuật toán hiệu quả.