-
-
Notifications
You must be signed in to change notification settings - Fork 39
Revert 156 revert 151 sk/no libuv sushi #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,14 @@ | ||
| mutable struct Multi | ||
| lock :: ReentrantLock | ||
| handle :: Ptr{Cvoid} | ||
| timer :: Ptr{Cvoid} | ||
| timer :: Timer | ||
| easies :: Vector{Easy} | ||
| grace :: UInt64 | ||
|
|
||
| function Multi(grace::Integer = typemax(UInt64)) | ||
| timer = jl_malloc(Base._sizeof_uv_timer) | ||
| uv_timer_init(timer) | ||
| multi = new(ReentrantLock(), C_NULL, timer, Easy[], grace) | ||
| multi = new(ReentrantLock(), C_NULL, Timer(0), Easy[], grace) | ||
| finalizer(multi) do multi | ||
| uv_timer_stop(multi.timer) | ||
| uv_close(multi.timer, cglobal(:jl_free)) | ||
| close(multi.timer) | ||
| done!(multi) | ||
| end | ||
| end | ||
|
|
@@ -32,19 +29,11 @@ end | |
|
|
||
| # adding & removing easy handles | ||
|
|
||
| function cleanup_callback(uv_timer_p::Ptr{Cvoid})::Cvoid | ||
| ## TODO: use a member access API | ||
| multi_p = unsafe_load(convert(Ptr{Ptr{Cvoid}}, uv_timer_p)) | ||
| multi = unsafe_pointer_to_objref(multi_p)::Multi | ||
| done!(multi) | ||
| return | ||
| end | ||
|
|
||
| function add_handle(multi::Multi, easy::Easy) | ||
| lock(multi.lock) do | ||
| if isempty(multi.easies) | ||
| preserve_handle(multi) | ||
| uv_timer_stop(multi.timer) # stop grace timer | ||
| close(multi.timer) # stop grace timer | ||
| end | ||
| push!(multi.easies, easy) | ||
| init!(multi) | ||
|
|
@@ -57,11 +46,14 @@ function remove_handle(multi::Multi, easy::Easy) | |
| @check curl_multi_remove_handle(multi.handle, easy.handle) | ||
| deleteat!(multi.easies, findlast(==(easy), multi.easies)::Int) | ||
| !isempty(multi.easies) && return | ||
| cleanup_cb = @cfunction(cleanup_callback, Cvoid, (Ptr{Cvoid},)) | ||
| if multi.grace <= 0 | ||
| done!(multi) | ||
| elseif 0 < multi.grace < typemax(multi.grace) | ||
| uv_timer_start(multi.timer, cleanup_cb, multi.grace, 0) | ||
| multi.timer = Timer(multi.grace/1000) do | ||
| lock(multi.lock) do | ||
| isopen(multi.timer) && done!(multi) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is necessary both because it might have closed while we were waiting for the lock, and because the callback form does not check this.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I misunderstood then.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might have said it wrong too
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to check
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| end | ||
| end | ||
| end | ||
| unpreserve_handle(multi) | ||
| end | ||
|
|
@@ -73,15 +65,14 @@ function set_defaults(multi::Multi) | |
| # currently no defaults | ||
| end | ||
|
|
||
| # libuv callbacks | ||
| # multi-socket handle state updates | ||
|
|
||
| struct CURLMsg | ||
| msg :: CURLMSG | ||
| easy :: Ptr{Cvoid} | ||
| code :: CURLcode | ||
| end | ||
|
|
||
| # should already be locked | ||
| function check_multi_info(multi::Multi) | ||
| while true | ||
| p = curl_multi_info_read(multi.handle, Ref{Cint}()) | ||
|
|
@@ -104,37 +95,13 @@ function check_multi_info(multi::Multi) | |
| end | ||
| end | ||
|
|
||
| function event_callback( | ||
| uv_poll_p :: Ptr{Cvoid}, | ||
| status :: Cint, | ||
| events :: Cint, | ||
| )::Cvoid | ||
| ## TODO: use a member access API | ||
| multi_p = unsafe_load(convert(Ptr{Ptr{Cvoid}}, uv_poll_p)) | ||
| multi = unsafe_pointer_to_objref(multi_p)::Multi | ||
| sock_p = uv_poll_p + Base._sizeof_uv_poll | ||
| sock = unsafe_load(convert(Ptr{curl_socket_t}, sock_p)) | ||
| flags = 0 | ||
| events & UV_READABLE != 0 && (flags |= CURL_CSELECT_IN) | ||
| events & UV_WRITABLE != 0 && (flags |= CURL_CSELECT_OUT) | ||
| lock(multi.lock) do | ||
| @check curl_multi_socket_action(multi.handle, sock, flags) | ||
| check_multi_info(multi) | ||
| end | ||
| end | ||
| # curl callbacks | ||
|
|
||
| function timeout_callback(uv_timer_p::Ptr{Cvoid})::Cvoid | ||
| ## TODO: use a member access API | ||
| multi_p = unsafe_load(convert(Ptr{Ptr{Cvoid}}, uv_timer_p)) | ||
| multi = unsafe_pointer_to_objref(multi_p)::Multi | ||
| lock(multi.lock) do | ||
| @check curl_multi_socket_action(multi.handle, CURL_SOCKET_TIMEOUT, 0) | ||
| check_multi_info(multi) | ||
| end | ||
| function do_multi(multi::Multi) | ||
| @check curl_multi_socket_action(multi.handle, CURL_SOCKET_TIMEOUT, 0) | ||
| check_multi_info(multi) | ||
| end | ||
|
|
||
| # curl callbacks | ||
|
|
||
| function timer_callback( | ||
| multi_h :: Ptr{Cvoid}, | ||
| timeout_ms :: Clong, | ||
|
|
@@ -143,15 +110,15 @@ function timer_callback( | |
| multi = unsafe_pointer_to_objref(multi_p)::Multi | ||
| @assert multi_h == multi.handle | ||
| if timeout_ms == 0 | ||
| lock(multi.lock) do | ||
| @check curl_multi_socket_action(multi.handle, CURL_SOCKET_TIMEOUT, 0) | ||
| check_multi_info(multi) | ||
| end | ||
| do_multi(multi) | ||
| elseif timeout_ms >= 0 | ||
| timeout_cb = @cfunction(timeout_callback, Cvoid, (Ptr{Cvoid},)) | ||
| uv_timer_start(multi.timer, timeout_cb, max(1, timeout_ms), 0) | ||
| multi.timer = Timer(timeout_ms/1000) do timer | ||
| lock(multi.lock) do | ||
| isopen(multi.timer) && do_multi(multi) | ||
| end | ||
| end | ||
| elseif timeout_ms == -1 | ||
| uv_timer_stop(multi.timer) | ||
| close(multi.timer) | ||
| else | ||
| @async @error("timer_callback: invalid timeout value", timeout_ms) | ||
| return -1 | ||
|
|
@@ -164,46 +131,47 @@ function socket_callback( | |
| sock :: curl_socket_t, | ||
| action :: Cint, | ||
| multi_p :: Ptr{Cvoid}, | ||
| uv_poll_p :: Ptr{Cvoid}, | ||
| watcher_p :: Ptr{Cvoid}, | ||
| )::Cint | ||
| if action ∉ (CURL_POLL_IN, CURL_POLL_OUT, CURL_POLL_INOUT, CURL_POLL_REMOVE) | ||
| @async @error("socket_callback: unexpected action", action) | ||
| return -1 | ||
| end | ||
| multi = unsafe_pointer_to_objref(multi_p)::Multi | ||
| if watcher_p != C_NULL | ||
| old_watcher = unsafe_pointer_to_objref(watcher_p)::FDWatcher | ||
| @check curl_multi_assign(multi.handle, sock, C_NULL) | ||
| unpreserve_handle(old_watcher) | ||
| end | ||
| if action in (CURL_POLL_IN, CURL_POLL_OUT, CURL_POLL_INOUT) | ||
| if uv_poll_p == C_NULL | ||
| uv_poll_p = uv_poll_alloc() | ||
| uv_poll_init(uv_poll_p, sock) | ||
| ## TODO: use a member access API | ||
| unsafe_store!(convert(Ptr{Ptr{Cvoid}}, uv_poll_p), multi_p) | ||
| sock_p = uv_poll_p + Base._sizeof_uv_poll | ||
| unsafe_store!(convert(Ptr{curl_socket_t}, sock_p), sock) | ||
| lock(multi.lock) do | ||
| @check curl_multi_assign(multi.handle, sock, uv_poll_p) | ||
| readable = action in (CURL_POLL_IN, CURL_POLL_INOUT) | ||
| writable = action in (CURL_POLL_OUT, CURL_POLL_INOUT) | ||
| watcher = FDWatcher(OS_HANDLE(sock), readable, writable) | ||
| preserve_handle(watcher) | ||
| watcher_p = pointer_from_objref(watcher) | ||
| @check curl_multi_assign(multi.handle, sock, watcher_p) | ||
| task = @async while true | ||
| events = try wait(watcher) | ||
| catch err | ||
| err isa EOFError && break | ||
| rethrow() | ||
| end | ||
| end | ||
| events = 0 | ||
| action != CURL_POLL_IN && (events |= UV_WRITABLE) | ||
| action != CURL_POLL_OUT && (events |= UV_READABLE) | ||
| event_cb = @cfunction(event_callback, Cvoid, (Ptr{Cvoid}, Cint, Cint)) | ||
| uv_poll_start(uv_poll_p, events, event_cb) | ||
| elseif action == CURL_POLL_REMOVE | ||
| if uv_poll_p != C_NULL | ||
| uv_poll_stop(uv_poll_p) | ||
| uv_close(uv_poll_p, cglobal(:jl_free)) | ||
| flags = CURL_CSELECT_IN * isreadable(events) + | ||
| CURL_CSELECT_OUT * iswritable(events) + | ||
| CURL_CSELECT_ERR * events.disconnect | ||
| lock(multi.lock) do | ||
| @check curl_multi_assign(multi.handle, sock, C_NULL) | ||
| @check curl_multi_socket_action(multi.handle, sock, flags) | ||
| check_multi_info(multi) | ||
| end | ||
| end | ||
| else | ||
| @async @error("socket_callback: unexpected action", action) | ||
| return -1 | ||
| @isdefined(errormonitor) && errormonitor(task) | ||
| end | ||
| @isdefined(old_watcher) && close(old_watcher) | ||
| return 0 | ||
| end | ||
|
|
||
| function add_callbacks(multi::Multi) | ||
| # stash multi handle pointer in timer | ||
| multi_p = pointer_from_objref(multi) | ||
| ## TODO: use a member access API | ||
| unsafe_store!(convert(Ptr{Ptr{Cvoid}}, multi.timer), multi_p) | ||
|
|
||
| # set timer callback | ||
| timer_cb = @cfunction(timer_callback, Cint, (Ptr{Cvoid}, Clong, Ptr{Cvoid})) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing argument
do t