Re: On nsICancelableRunnable (or how bad decisions come back to haunt you)

2016-03-14 Thread Gabriele Svelto
On 13/03/2016 09:22, Kyle Huey wrote:
> Much of the "disease" you see is simply support for DOM worker threads,
> because every runnable that can run on those threads must be
> cancelable.  Workers do not guarantee one of the invariants that other
> XPCOM threads do: that every runnable is eventually run after being
> successfully dispatched.  Instead we guarantee that every runnable is
> either Run() or Cancel()ed.

Yeah, that's something I had noticed and I was trying to understand why.
So it seems that this interface actually turned out to have a proper use
after all.

> The disadvantage of pushing this into the event queue is that today
> runnables that are dispatched from other threads to workers *must*
> implement nsICancelableRunnable, which means authors of code that runs
> on workers must think about this.  We do already have an exception for
> NS_DispatchToCurrentThread though (via ExternalRunnableWrapper), so this
> may be something we can relax.  It would generally require us to write
> cleanup code (for the existing runnables and any future ones) to run
> from destructors, and historically destructors could run on either the
> dispatching thread or the executing thread (although that has changed
> somewhat.)

My gripes with its original design is that it's inherently
non-thread-safe and non-atomic (i.e. Cancel() can be called while Run()
is being executed) and it essentially drops the burden of implementing
proper cancellation on the user. My idea of handling cancellation
externally was motivated by having the operation be both thread-safe and
fully atomic (either something runs or it doesn't). This however implies
that if the task was fire-and-forget, then destruction will always be
done by the canceling thread and will happen immediately; in the current
scenario destruction will be done by the thread owning the queue, and it
will happen only when the runnable is drained from it.

> Regardless, your plan should probably involve me ;)

Yeah, this was my idea when nsICancelableRunnable was practically only
used in FxOS-specific code to support canceling potentially long-running
operations posted on the main thread (and which might have not executed
yet). Since it's use has evolved it might not be worth pursuing it
anymore, which is why I wanted to hear about how it's been used now.

> PS. Subscribe to the mailing list so you don't get caught in moderation.

I'm already subscribed, I just verified it, it's bizarre that the
message was held :-/

 Gabriele



signature.asc
Description: OpenPGP digital signature
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: On nsICancelableRunnable (or how bad decisions come back to haunt you)

2016-03-13 Thread Kyle Huey
On Fri, Mar 11, 2016 at 7:04 AM, Gabriele Svelto 
wrote:

>  Many moons ago, while we were frantically trying to make Firefox OS 1.0
> run half-decently, I introduced a derived class of nsIRunnable that
> could be canceled: nsICancelableRunnable. As with many other things that
> led to the first release of FxOS this was done in a rush and without
> much thinking. It's only goal at the time was to allow me to cancel a
> single, simple, stateless runnable that could take a while to run.
>
> Thinking about it afterwards I came to the conclusion that this was a
> terrible approach: implementing the Cancel() method was up to the user
> and there was no telling on which threads Run() and Cancel() could be
> called making it potentially racy. So I thought it could be replaced by
> adding a Cancel() method to the event queue that would just remove the
> event in a thread-safe way. This seemed a cleaner, safer approach.
>
> But then I looked into our code and discovered that
> nsICancelableRunnable has spread like a disease through the codebase and
> it's systematically used in workers to let us cancel events posted to
> them. Ouch. Some of its uses highlight its problems: in some cases its
> only purpose is to force calling the Run() method by the calling thread
> so that certain objects get destroyed on that thread (possibly to
> prevent leaks). In other cases we have patterns like this:
>
> Run() {
>   if (mDoSomething) {
> DoSomething();
>   }
> }
>
> Cancel() {
>   mDoSomething = false;
> }
>
> Which is fine if both methods are called by the same thread, but most
> likely not if they're called on different threads and the interface
> itself does nothing to prevent you from doing it.
>
> All in all I'd still like to get rid of it but I'm not sure if my
> original approach of moving the cancel functionality into the EventQueue
> is the right way to go. Which leads me to the point of this e-mail: to
> gather feedback on my idea to get rid of it. Since I don't have enough
> knowledge about all the affected areas I'd like to hear from those who
> actually used it.


On workers Run and Cancel are always called by the same thread, so there is
no race.

Much of the "disease" you see is simply support for DOM worker threads,
because every runnable that can run on those threads must be cancelable.
Workers do not guarantee one of the invariants that other XPCOM threads do:
that every runnable is eventually run after being successfully dispatched.
Instead we guarantee that every runnable is either Run() or Cancel()ed.

The disadvantage of pushing this into the event queue is that today
runnables that are dispatched from other threads to workers *must*
implement nsICancelableRunnable, which means authors of code that runs on
workers must think about this.  We do already have an exception for
NS_DispatchToCurrentThread though (via ExternalRunnableWrapper), so this
may be something we can relax.  It would generally require us to write
cleanup code (for the existing runnables and any future ones) to run from
destructors, and historically destructors could run on either the
dispatching thread or the executing thread (although that has changed
somewhat.)

Regardless, your plan should probably involve me ;)

- Kyle

PS. Subscribe to the mailing list so you don't get caught in moderation.
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


On nsICancelableRunnable (or how bad decisions come back to haunt you)

2016-03-13 Thread Gabriele Svelto
 Many moons ago, while we were frantically trying to make Firefox OS 1.0
run half-decently, I introduced a derived class of nsIRunnable that
could be canceled: nsICancelableRunnable. As with many other things that
led to the first release of FxOS this was done in a rush and without
much thinking. It's only goal at the time was to allow me to cancel a
single, simple, stateless runnable that could take a while to run.

Thinking about it afterwards I came to the conclusion that this was a
terrible approach: implementing the Cancel() method was up to the user
and there was no telling on which threads Run() and Cancel() could be
called making it potentially racy. So I thought it could be replaced by
adding a Cancel() method to the event queue that would just remove the
event in a thread-safe way. This seemed a cleaner, safer approach.

But then I looked into our code and discovered that
nsICancelableRunnable has spread like a disease through the codebase and
it's systematically used in workers to let us cancel events posted to
them. Ouch. Some of its uses highlight its problems: in some cases its
only purpose is to force calling the Run() method by the calling thread
so that certain objects get destroyed on that thread (possibly to
prevent leaks). In other cases we have patterns like this:

Run() {
  if (mDoSomething) {
DoSomething();
  }
}

Cancel() {
  mDoSomething = false;
}

Which is fine if both methods are called by the same thread, but most
likely not if they're called on different threads and the interface
itself does nothing to prevent you from doing it.

All in all I'd still like to get rid of it but I'm not sure if my
original approach of moving the cancel functionality into the EventQueue
is the right way to go. Which leads me to the point of this e-mail: to
gather feedback on my idea to get rid of it. Since I don't have enough
knowledge about all the affected areas I'd like to hear from those who
actually used it.

 Gabriele



signature.asc
Description: OpenPGP digital signature
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform