If you don't want to use pipes to synchronize your threads, the only
function that is safe to use from another thread (or signal handler)
is uv_async_send. Any other function will cause undefined behavior. It
may occasionally work, but it will probably also corrupt other random
parts of the program.

-Jameson

On Fri, Jan 31, 2014 at 5:05 PM, Tim Holy <[email protected]> wrote:
> This is very helpful, thanks for the tips. I especially like the idea of
> waiting on a file descriptor controlled by a C thread; that should avoid the
> need for any Julia code to be called by the callback.
>
> You may be interested in some experiments I ran (see below), trying to
> reproduce my problem in a simpler context. "Unfortunately," all of these
> experiments work. So either there is something specific to this particular
> library, or "working" is fragile in some fashion and I just haven't succeeded
> in triggering a failure.
>
> --Tim
>
> c = Condition()
>
> function c_notify(p::Ptr{Void})
>     cond = unsafe_pointer_to_objref(p)
>     notify(cond)
>     C_NULL
> end
>
> const cb = cfunction(c_notify, Ptr{Void}, (Ptr{Void},))
>
> @sync begin
>     @async begin
>         println("About to wait from 1")
>         wait(c)
>         println("Done waiting from 1")
>     end
>     @async begin
>         println("About to notify from 2")
> #         notify(c)
>         ccall(cb, Void, (Ptr{Void},), pointer_from_objref(c))
>         println("Done notifying from 2")
>     end
> end
>
> threads = Uint64[0]
>
> @sync begin
>     @async begin
>         println("About to wait from 1")
>         wait(c)
>         println("Done waiting from 1")
>     end
>     @async begin
>         println("About to notify from 2")
> #         notify(c)
>         ccall(:pthread_create, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void},
> Ptr{Void}), threads, C_NULL, cb, pointer_from_objref(c))
>         ccall(:pthread_join, Cint, (Uint64, Ptr{Void}), threads[1], C_NULL)
>         println("Done notifying from 2")
>     end
> end
>
>
> On Friday, January 31, 2014 01:50:53 PM Spencer Russell wrote:
>> Hi Tim,
>>
>> I spent some time playing around with interfacing to multi-threaded C
>> libraries for AudioIO, namely portaudio. In Portaudio you register a
>> callback which gets called periodically whenever the audio card needs a new
>> frame of data. It gets called from a separate thread, so I was getting
>> segfaults if I executed julia code directly from the callback.
>>
>> In the end I wrote a small C module that implemented a callback which I
>> kept synchronized with a Julia Task. For the C callback to wake up the Task
>> I used a file descriptor (that way in Julia land I could wait on it and
>> only block that task instead of the whole julia process). For the Julia
>> Task to wake up the C callback I used a semaphore.
>>
>> You can see my C code (as well as the BinDeps stuff to compile it) in the
>> AudioIO repo at
>>
>> https://github.com/ssfrr/AudioIO.jl
>>
>> I'm not sure if this approach would work in your situation, but if your C
>> library is spawning a separate thread I think this is one way to handle it.
>>
>> -s
>>
>> On Fri, Jan 31, 2014 at 7:58 AM, Tim Holy <[email protected]> wrote:
>> > I'm interfacing with a C library that provides the ability to set a
>> > callback
>> > function so you can be notified when some job is done. I'm hoping to
>> > exploit
>> > this with the Task interface so I can feed multiple jobs with a single
>> > Julia
>> > process. I'm declaring my notify function like this:
>> >
>> > function callback_notify(hnd, status, data)
>> >
>> >     println("In notify")
>> >     s = unsafe_pointer_to_objref(data)::Stream
>> >     @show s
>> >     s.status = status
>> >     notify(s.c)
>> >     println("Done notifying")
>> >     nothing
>> >
>> > end
>> >
>> > Stream is a type that has a Condition member,
>> > type Stream
>> >
>> >     handle::StreamHandle
>> >     status::Cuint
>> >     c::Condition
>> >
>> > end
>> >
>> > I've successfully set the callback function, issued wait(s.c), and from
>> > the
>> > println statements I can see that the notify callback executes fully.
>> > However,
>> > my task never wakes up. My suspicion is that the C library is spawning a
>> > new
>> > thread; does that pose problems for the Task interface? Or is something
>> > else
>> > happening? Any good workarounds?
>> >
>> > --Tim

Reply via email to