Tôi đã thực hiện việc này cho một bài tập về nhà mà không cần viết bất kỳ trình biên dịch nào cả. Cơ chế chuyển đổi luồng là setjmp
/longjmp
. Điều này liên quan đến việc phân bổ bộ nhớ cho ngăn xếp của mỗi luồng, sau đó rất cẩn thận xoa bóp các giá trị trong jmp_buff
vì vậy việc thực hiện chuyển sang ngăn xếp của chuỗi tiếp theo.
Xem thêm của Russ Cox có thể đọc được libtask.
Chỉnh sửa để phản hồi nhận xét của OP: Khi quyết định thời điểm chuyển chủ đề có hai hướng chính: preemptive & hợp tác xã. Trong mô hình ưu tiên, bạn sẽ có thứ gì đó giống như tín hiệu hẹn giờ làm cho luồng thực thi chuyển sang luồng điều phối trung tâm, trong đó chọn luồng tiếp theo để chạy. Trong mô hình hợp tác, các chuỗi “thu được” với nhau, hoặc rõ ràng (ví dụ:, bằng cách gọi hàm yield()
bạn sẽ cung cấp) hoặc ngầm (ví dụ:, yêu cầu khóa do một chuỗi khác giữ).
Hãy xem API của libtask để biết ví dụ về mô hình hợp tác, đặc biệt mô tả chức năng taskyield()
. Đó là sản lượng rõ ràng mà tôi đã đề cập. Ngoài ra còn có các chức năng I/O không chặn trong đó bao gồm một năng suất tiềm ẩn - “nhiệm vụ” hiện tại được giữ cho đến khi I/O hoàn tất, nhưng các nhiệm vụ khác có cơ hội để chạy.
Nguồn
2012-02-05 00:20:04
Bài tập có một chút khó khăn để thỏa mãn vì không thể thực hiện được "trong C". Bạn cần ít nhất một số lượng tối thiểu của assembly hoặc các phần mở rộng trình biên dịch tương đương để tạo thuận lợi cho việc tạo ra các bối cảnh thực thi mới và chuyển đổi giữa chúng. Hoặc bạn có thể viết máy ảo hoàn chỉnh của riêng mình và triển khai C để chạy trên máy ảo, nhưng tôi không nghĩ rằng đó là những gì người hướng dẫn của bạn có trong đầu ... –
Đối với đa nhiệm hợp tác/luồng, bạn có thể tìm thấy getcontext/makecontext/chức năng setcontext hữu ích. – MetallicPriest
Tôi không thể thấy làm thế nào điều này có thể được thực hiện mà không cần một số assembler để thực hiện việc tiết kiệm/khôi phục lại bối cảnh đăng ký và ngăn xếp con trỏ. Đó là mà không cần xem xét I/O và làm thế nào để chờ đợi nó. –