1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| ┌──────────────────────────┐ │ │ │ │ │ co 1 │ │ │ │ 1. curl exec │ │ │ │ │ └──────────────────────────┘ │ │ ▼ ┌──────────────────────────┐ │ │ │ │ │ co 1 │ │ │ │ 2. add timer │ │ │ │ │ └──────────────────────────┘ │ │ ▼ ┌──────────────────────────┐ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ co 1 │ │ event loop │ │ curl_multi_socket_action -> │ │ │────────────────────────────────────▶│ │──────────▶│ connect -> add write event -> │ │ 3. yield_m │ │ 4. timeout │ │ return to event loop │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────┘ └──────────────────────────────────┘ └──────────────────────────────────┘ │ │ │ ▼ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ │ event loop │ │ curl_multi_socket_action -> send │ │ │──────────▶│ request -> add read event -> │ │ 5. writeable │ │ return to event loop │ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ └──────────────────────────────────┘ │ │ │ │ │ ▼ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ 6.3 curl_multi_socket_action -> │ │ event loop │ │ 6.1 curl_multi_socket_action -> │ │CURLOPT_WRITEFUNCTION func -> read│ │ │──────────▶│ call CURLOPT_HEADERFUNCTION │─────────▶│body -> delete all event -> delete│ │ 6. readable │ │ │ │ timer -> resume_m │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ └──────────────────────────────────┘ └──────────────────────────────────┘ │ │ │ │ │ │ if set CURLOPT_HEADER│UNCTION in user code │ │ │ │ │ ▼ ▼ ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ │6.2 set write_header for coroutine│ │ 6.4 read_info -> CURLMSG_DONE -> │ │ -> resume_m │ │ resume_m │ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ │ │ │ └──────────────────────────────────┘ │ │ │ │ │ │ ▼ │ ┌────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ co 1 │ │ │ │ │ │write_header func to get response header -> │ │ │ yield_m (Notice: Every time the │ │ │fn_write_header reads a row of headers in a │ │ │callback, a scheduler-to-coroutine switch is│ │ │ required) │ │ │ │ │ │ why we should call it in coroutine? │ │ │ Because this callback function may have │ │ │ blocking IO │ │ │ │ │ │ │ │ └────────────────────────────────────────────┘ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ co 1 │ │ │ │◀─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ │ 7. continue to run... │ │ │ │ │ └──────────────────────────────────────────────┘
|