@jmcardon
how would you feel about
RTS
and removing anywhere requiringimplicit Timer[F]
We talked about it before. I don't like it because Timer
is not a RTS
and also Timer
is meant for generic code, thus working for any F[_]
. That IO
requires an implicit Timer
(or ContextShift
) for certain operations, that's just an implementation detail of IO
that doesn't extend to other implementations (more specifically Monix's Task
does not require it, yet Timer
is very useful for Monix's Task
as well).
The other reason for why I'm against a RTS
is because cats.effect.IO
is very light, not having any requirements for unsafeRunAsync
and that's a virtue because it can be used in more contexts.
Before discussing this any further however, if you feel strongly about introducing a RTS
, I encourage you to go through the exercise of designing one. It's not that easy.
and a third question
e.g. you'd use a different Timer in tests, when running your F
s, any scenario in you need that without having to run things?
val p = IO.pure(())
val to = IO.sleep(1.seconds)
def loop(): IO[Unit] = {
IO.race(to, p)
.flatMap(_ => loop())
}
val p = IO.pure(())
val to = IO.sleep(1.seconds)
def loop(): IO[Unit] = {
IO.race(to, p)
.flatMap(_ => loop())
}
@SystemFw @TomasStanek no, this sample shouldn't leak in the current version, however note that race
is pretty resource intensive so in loops like this the garbage collector might not cope well.
until the losing sleeper has been cancelled
N.B. cancelling a scheduled tick is instant, but it depends on the thread-pool's implementation if the resources are cleared immediately or if the entry is just marked for deletion at a later point in time. Obviously scheduling a lot of sleeps in a hot loop isn't such a good idea.
bracket
.
We've got our milestone plan π
https://github.com/typelevel/cats-effect/milestone/6
Let's close these and release 1.0.0-RC3.
1) where are the yield points in cats-effect implementation of concurrency
Only in race conditions, e.g. start
, race
. In general these operations are very rare, in my experience most of the time people just use chains of flatMaps, which don't require concurrency support. This is one reason I like IO
's current implementation.
2) how does Monix Task implement Concurrent without requiring Timer (or something to shift)
Task
requires a Scheduler
in its runAsync
to be provided by the environment, which makes Timer
pure. This is basically the equivalent of the RTS that you want. However I want our types to support both Monix Task and the current IO and even the former (pre 0.10) IO, otherwise the types are not generic enough. The problem with a RTS is that it is implementation specific, whereas Timer
is polymorphic.
Is there any scenario in which you'd want a different Timer but you are not unsafeRunning something?
Ideally no such scenario should happen, however in your typical JVM application, due to the libraries being used and to JVM processes being built to be fat (with lots of features), what happens is that users have to choice but to juggle with multiple thread-pools.
Just to give an example, last time I used MongoDB, I used the ReactiveMongo client for Scala which insists on starting its own Akka System with its own thread-pool of course. Which is stupid of course, but once you have that in your process, you have to work with it and thus keep Mongo-related operations on the Mongo-related thread-pool. And this doesn't happen due to sloppiness. I'm a very careful developer yet on one of the components I was in charge at E.On I counted no less than 6 thread-pools in the same process and I can only guess what goes on in the JVM projects built by beginners.
On top of Haskell maybe I'd agree, because Haskell doesn't do 1:1 kernel level multi-threading, but on platforms such as the JVM, you cannot have "coherency" for Timer or the newly added ContextShift.
Effect[Task]
? Effect[Scheduler => Task]
?
start
works, in particular the interleaving of different F
s
Only in race conditions, e.g. start, race.
start
and race
, they wouldn't need ContextShift
/ Timer
if we wouldn't have made them to auto-fork before executing the involved tasks
@TomasStanek
@alexandru It's not about being GC heavy, it's about that the loop brings jvm gradually to halt. (I'm observing that with 1.0.0-RC2, and I'll try that with 1.0.0-RC3 when it's out). What you say is therefore that the cancelation is not synchronized (and will never be - it is by design) and the user must therefore employ other means of synchronization, if there are some resources to be freed to continue safely, right?
What do you mean by cancelation not being synchronized?
I will test, but no, race
shouldn't leak if the underlying scheduler doesn't and if the underlying scheduler leaks, then there's nothing we can do.
I'm not discounting the possibility of a bug, but if you're having problems, it has nothing to do with #305
So if you get more hints, open an issue.