Another way to fix usb would be to re-register the callback after a previously registered callback is fired. Of course it is cheaper not to have to re-register, but re-registration in the latest IO manager should be fairly cheap, so this may not be a performance problem for usb. Would this work for you?

You could also use a CPP directive to only do this for GHC 7.8 and up.

If we want to allow usb to work unchanged, then we will have to revert to the non-ONE_SHOT behavior of registerFd and add some things to the API to allow GHC.Thread to register with ONE_SHOT behavior. Reverting could break clients of this semi-public API who have adapted to the 7.8 behavior.  There probably aren't of these clients other than GHC.Thread, so this may not be a big issue.

To do per-FD setting of ONE_SHOT or not, we actually need to have per-subscription settings, since there can be multiple invocations to register callbacks for a single file descriptor (e.g. from two different threads) and they might want different settings. If all the clients want ONE_SHOT we use ONE_SHOT registration, if all want persistent registrations we don't use ONE_SHOT. If it is mixed, then the manager has to choose one or the other and simulate the required behavior for the other registrations (e.g. choose persistent and automatically unregister for ONE_SHOT registrations). We could either always make the same choice (e.g. if there is a mix, use persistent), or we could have per-FD setting that is configurable by clients. 

Andi


On Sat, Oct 11, 2014 at 9:31 AM, Andreas Voellmy <andreas.voellmy@gmail.com> wrote:


On Sat, Oct 11, 2014 at 1:07 AM, Ben Gamari <bgamari.foss@gmail.com> wrote:
Thanks for your quick reply!


Andreas Voellmy <andreas.voellmy@gmail.com> writes:

> On Sat, Oct 11, 2014 at 12:17 AM, Ben Gamari <bgamari.foss@gmail.com> wrote:
>>
>> I'm a bit perplexed as to why the change was made in the way that it
>> was.  Making one-shot a event-manager-wide attribute seems to add a fair
>> bit of complexity to the subsystem while breaking backwards
>> compatibility with library code.
>
>
> It added some complexity to the IO manager, but that should not affect
> clients except those using the internal interface.
>
What I'm wondering is what the extra complexity bought us. It seems like
the same thing could have been achieved with less breakage by making
this per-fd instead of per-manager. I may be missing something, however.


Generally, ONE_SHOT helped improve performance. I agree with you that it may be possible to do this on a per-FD basis. I'll look into what it would take to do this.

 
>
>> Going forward library authors now need
>> to worry about whether the system event manager is one-shot or not.
>
>
> Yes, but only library authors using the internal interface.
>
>
>> Not
>> only is this platform dependent but it seems that there is no way for a
>> user to determine which semantics the system event handler uses.
>
>
>> Is there a reason why one-shot wasn't exported as a per-fd attribute
>> instead of per-manager? Might it be possible to back out this change and
>> instead add a variant of `registerFd` which exposes one-shot semantics?
>>
>>
> The system event manager is configured by GHC.Thread using ONE_SHOT if the
> system supports it.
>
> You can always create your own EventManager using GHC.Event.Manager.new or
> GHC.Event.Manager.newWith functions. Those functions take a Bool argument
> that control whether ONE_SHOT is used by the Manager returned by that
> function (False means not to use ONE_SHOT). Would this work for usb?
>
I had considered this but looked for other options for two reasons,

 * `loop` isn't exported by GHC.Event

Right - it wouldn't make sense to export the system EventManager's loop. However, the GHC.Event.Manager module does export its loop function, so if you create your own non-ONE_SHOT event manager, you can just invoke its loop function.
 
 * there is already a perfectly usable event loop thread in existence

I'm a bit curious to know what advantages ONE_SHOT being per-manager
carries over per-fd. If the advantages are large enough then we can just
export `loop` and be done with it but the design as it stands strikes me
as a bit odd.

I suspect that a per-FD design would perform just as well, but I need to look at the details to be sure.


Cheers,

- Ben