No subject

Fri Aug 26 17:16:24 CEST 2011

openDevice =E2=88=B7 Device =E2=86=92 IO DeviceHandle

and perform IO with them:

readBulk =E2=88=B7 DeviceHandle =E2=86=92 EndpointAddress =E2=86=92 Size =
=E2=86=92 Timeout =E2=86=92 IO
(B.ByteString, Status)

Internally the synchronous `readBulk` is implemented using
asynchronous IO: first a request to read bytes from a USB device is
asynchronously submitted. Then it waits on a lock (`takeMVar lock`).
When the bytes are read an event is fired on a certain file
descriptor. The GHC event manager then wakes up and calls a callback
which will release the lock (`putMVar lock ()`).

I choose to have one event loop per session (`Ctx`) with the usb
library. This means that I make a new `EventManager` in `newCtx`:

evtMgr =E2=86=90

register the `libusb` file descriptors with the event manager and fork
a thread which will `loop` the `EventManager`:

tid <- forkIOWithUnmask $ \unmask =E2=86=92 unmask $ EventManager.loop evtM=

The underlying `libusb` C library needs to be deinitialized when
you're done with it. However for safety and ease of use a user of my
Haskell library doesn't need to explicitly deinitialize the library.
Instead this happens automatically when the garbage collector collects
an unreferenced `Ctx` by registering (using
`Foreign.Concurrent.newForeignPtr`) the following finalizer with the
`Ctx` foreign pointer:

    -- Stop the event handling loop by killing its thread:
    killThread tid
    -- Finally deinitialize libusb:
    c'libusb_exit ctxPtr

As you see I also kill the thread which is running the event manager
loop. However I think this is not the right way to do it because when
I use the library I see the following message being continually
printed after the `Ctx` is finalized:

ghc: ioManagerWakeup: write: Bad file descriptor

Note that when I remove the `killThread tid` the messages disappear.

It seems that killing the event manager loop is not allowed. Is there
another way of shutting down the event manager loop?

I know I can shut it down by using the `shutdown` function. However
this function is asynchronous. This won't work because I need to make
sure the event loop is shutdown before I exit the `libusb` library
(because that will close the file descriptors that the event loop is
working with).

I see the event manager provides the `finished` function which will
poll the manager to see if it stopped looping. This function is not
exported however. Is it possible to export this function?

It would be even nicer to have a synchronous shutdown function so that
I don't need to setup a loop that waits till the manager has been shut



More information about the Glasgow-haskell-users mailing list