2015-12-29 59 views
5

Trong khi thực hiện một giao thức truyền thông, chúng tôi có một bộ mã hóa truyền tải một số cấu trúc đệ quy và mã hóa chúng thành một thông điệp nhị phân.coroutines đệ quy trong C (C99)

Cho đến nay rất tốt, nhưng bây giờ bộ đệm phải tách thành nhiều phần có kích thước cố định, ví dụ: kích thước trên của bộ đệm nhận. Vì việc cấp phát bộ nhớ cho toàn bộ thông điệp và cắt nó có vẻ quá lãng phí (kích thước của thông điệp là - trong lý thuyết - không bị ràng buộc), ý tưởng bây giờ là triển khai một coroutine với phương tiện setjmp/longjmp.

Hiện tại, tôi có một nguyên mẫu với hai bộ đệm nhảy - một bộ đệm để tiếp tục chức năng mã hóa và hàm thứ hai để mô phỏng hành vi trả về của hàm để quay lại người gọi.

Vâng, có vẻ như nó hoạt động, nhưng mã trông giống như đang đi thẳng từ địa ngục. Có bất kỳ 'quy ước' nào để thực hiện các chức năng đệ quy gián đoạn, có thể là một tập các macro hay cái gì đó không? Tôi chỉ muốn sử dụng các chức năng được tiêu chuẩn hóa, không có nội tuyến asm để duy trì di động.

Addition: Nguyên mẫu là ở đây: https://github.com/open62541/open62541/compare/master...chunking_longjmp Các 'sử dụng' được hiển thị bên trong bộ phận kiểm tra. Hiện tại, hành vi coroutine được thực hiện cho một hàm không đệ quy Array_encodeBinary. Tuy nhiên, hành vi 'coroutine' nên được mở rộng đến hàm đệ quy chung UA_encodeBinary nằm ở đây: https://github.com/open62541/open62541/blob/master/src/ua_types_encoding_binary.c#L1029

+0

Dường như bạn đã sẵn sàng chuyển sang ngôn ngữ lập trình Go. – chqrlie

+0

Có vẻ như bạn có thể sử dụng mẫu người tiêu dùng của nhà sản xuất. –

+2

Điều bạn đang cố gắng không được hỗ trợ bởi ISO C. Cách bạn đang sử dụng 'setjmp' và' longjmp' không bị xử phạt theo tiêu chuẩn, và không có thay thế trong "di động" C. Bạn có thể tìm thấy [ 'setcontext'] (http://linux.die.net/man/2/getcontext) và bạn bè * phần nào * nhiều hơn nữa, vì chúng thực sự được thiết kế cho trường hợp sử dụng này, nhưng chúng không có sẵn trên tất cả các nền tảng và chúng vẫn còn khá khó xử để sử dụng. – zwol

Trả lời

1

Như được chỉ ra bởi Olaf, cách dễ nhất là sử dụng thuật toán lặp lại. Tuy nhiên, nếu vì một lý do nào đó, điều này rất khó, bạn luôn có thể mô phỏng thuật toán đệ quy bằng một thùng chứa stack và một vòng lặp while. Điều này ít nhất làm cho chức năng dễ ngắt hơn. Bài viết khá hay về cách thực hiện điều này có thể được tìm thấy here. Bài viết được viết cho C++, nhưng không khó để chuyển đổi nó thành c.

+0

Việc triển khai phần mềm có thể sẽ có cùng một vấn đề với ngăn xếp thông thường (phần cứng). Trên thực tế, nó sẽ bổ sung thêm chi phí. Dù sao, tôi không nghĩ rằng đó là một câu trả lời, nhưng nhiều hơn một bình luận. – Olaf