# Tasks and type stability

**URL:** <https://discourse.julialang.org/t/tasks-and-type-stability/3212>\
**Category:** General Usage\
**Created:** [April 14, 2017, 8:00am UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212 "2017-04-14T08:00:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mbeltagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbeltagy/32/130_2.png) [@mbeltagy](https://discourse.julialang.org/u/mbeltagy)\
**Post date:** [April 14, 2017, 8:00am UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/1 "2017-04-14T08:00:39Z")

</div>

I was experimenting with [Julia’s coroutines](https://docs.julialang.org/en/stable/manual/control-flow/#man-tasks) to do some simple discrete event simulations.

I noticed that `consume` returns a type `Any`, as shown below. Performance could be much better if the returned type was known. Is there a way to do that?

```julia
function prtsk(tsk)
       for i=1:10
          u=consume(tsk)
          println(u)
       end
end
function yt()
       for i=1:10
           produce(i)
       end
end

ytt=Task(yt)

julia> prtsk(ytt)
1
2
3
4
5
6
7
8
9
10

```

```julia
julia> @code_warntype prtsk(ytt)
Variables:
  #self#::#prtsk
  tsk::Task
  #temp#::Int64
  i::Int64
  u::Any

Body:
  begin 
      SSAValue(2) = (Base.select_value)((Base.sle_int)(1,10)::Bool,10,(Base.box)(Int64,(Base.sub_int)(1,1)))::Int64
      #temp#::Int64 = 1
      3: 
      unless (Base.box)(Base.Bool,(Base.not_int)((#temp#::Int64 === (Base.box)(Int64,(Base.add_int)(SSAValue(2),1)))::Bool)) goto 15
      SSAValue(3) = #temp#::Int64
      SSAValue(4) = (Base.box)(Int64,(Base.add_int)(#temp#::Int64,1))
      i::Int64 = SSAValue(3)
      #temp#::Int64 = SSAValue(4) # line 3:
      u::Any = $(Expr(:invoke, LambdaInfo for consume(::Task), :(Main.consume), :(tsk))) # line 4:
      (Main.println)(u::Any)::Void
      13: 
      goto 3
      15: 
      return
  end::Void

```

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [April 14, 2017, 11:00am UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/2 "2017-04-14T11:00:08Z")

</div>

At a guess (untested), ytt is an object defined at global scope. Try putting it inside a function.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 14, 2017, 12:28pm UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/3 "2017-04-14T12:28:26Z")

</div>

`ytt` being a global doesn’t matter since it’s not used in the function. Type inference cannot see the control flow of coroutine so it can’t infer the return type of consume. You can add a type assert on it.

---

<div class="post-metadata">

**Author:** ![mbeltagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbeltagy/32/130_2.png) [@mbeltagy](https://discourse.julialang.org/u/mbeltagy)\
**Post date:** [April 15, 2017, 8:46am UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/4 "2017-04-15T08:46:15Z")

</div>

After some digging, I learned that the produce/consume approach is [deprecated in 0.6](https://github.com/JuliaLang/julia/issues/17699). The current [documentation](https://docs.julialang.org/en/latest/manual/control-flow.html#man-tasks-1) is quite sparse, however.

The help documentation makes it clear that a `Channel` type could be specified

I tried this new mechanism on 0.6.0-pre.alpha.231, but with little success

```julia

julia> function prtsk(c::Channel{Int})
                     for i=1:10
                        u=take!(c)
                        println(u)
                     end
              end
prtsk (generic function with 1 method)

julia> function yt(c::Channel)
              for i=1:10
                  put!(c,i)
              end
       end
yt (generic function with 1 method)

julia> chnl=Channel(yt,ctype=Int)
Channel{Int64}(sz_max:0,sz_curr:1)

julia> @code_warntype prtsk(chnl)
Variables:
  #self#::#prtsk
  c::Channel{Int64}
  i::Int64
  u::Any
  #temp#::Int64

Body:
  begin 
      SSAValue(2) = (Base.select_value)((Base.sle_int)(1, 10)::Bool, 10, (Base.sub_int)(1, 1)::Int64)::Int64
      #temp#::Int64 = 1
      3: 
      unless (Base.not_int)((#temp#::Int64 === (Base.add_int)(SSAValue(2), 1)::Int64)::Bool)::Bool goto 14
      SSAValue(3) = #temp#::Int64
      SSAValue(4) = (Base.add_int)(#temp#::Int64, 1)::Int64
      #temp#::Int64 = SSAValue(4) # line 3:
      u::Any = $(Expr(:invoke, MethodInstance for take!(::Channel{Int64}), :(Main.take!), :(c))) # line 4:
      (Main.println)(u::Any)::Void
      12: 
      goto 3
      14: 
      return
  end::Void

```

Not sure if this is by design, or would it warrant an issue.

---

<div class="post-metadata">

**Author:** ![mbeltagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbeltagy/32/130_2.png) [@mbeltagy](https://discourse.julialang.org/u/mbeltagy)\
**Post date:** [April 15, 2017, 9:45am UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/5 "2017-04-15T09:45:54Z")

</div>

Interestingly, if I use a slight different mechanism for Channel generation, I get slight better generated code.

```julia

julia> function yt()
              c=Channel{Int}(10)
              @async begin   
              for i=1:10
                  put!(c,i)
              end
              close(c)
              end
              c
       end
yt (generic function with 2 methods)

julia> chnl=yt()
Channel{Int64}(sz_max:10,sz_curr:10)
julia> @code_warntype prtsk(chnl)
Variables:
  #self#::#prtsk
  c::Channel{Int64}
  i::Int64
  u::Int64
  #temp#::Int64

Body:
  begin 
      SSAValue(4) = (Base.select_value)((Base.sle_int)(1, 10)::Bool, 10, (Base.sub_int)(1, 1)::Int64)::Int64
      #temp#::Int64 = 1
      3: 
      unless (Base.not_int)((#temp#::Int64 === (Base.add_int)(SSAValue(4), 1)::Int64)::Bool)::Bool goto 20
      SSAValue(5) = #temp#::Int64
      SSAValue(6) = (Base.add_int)(#temp#::Int64, 1)::Int64
      #temp#::Int64 = SSAValue(6) # line 3:
      SSAValue(2) = $(Expr(:invoke, MethodInstance for take!(::Channel{Int64}), :(Main.take!), :(c)))
      u::Int64 = (Core.typeassert)((Base.convert)(Main.Int, SSAValue(2))::Any, Main.Int)::Int64 # line 4:
      $(Expr(:inbounds, false))
      # meta: location coreio.jl println 5
      SSAValue(3) = (Core.typeassert)(Base.STDOUT, Base.IO)::IO
      # meta: pop location
      $(Expr(:inbounds, :pop))
      (Base.print)(SSAValue(3), u::Int64, $(QuoteNode('\n')))::Void
      18: 
      goto 3
      20: 
      return
  end::Void

```

So in this version `u` is of type `Int32` at the outset.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [April 15, 2017, 7:09pm UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/6 "2017-04-15T19:09:18Z")

</div>

I can’t reproduce your issue. The `@code_warntype` is free of type instabilities for me (except, of course, `STDOUT`).

Perhaps try updating to the latest beta?

---

<div class="post-metadata">

**Author:** ![mbeltagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbeltagy/32/130_2.png) [@mbeltagy](https://discourse.julialang.org/u/mbeltagy)\
**Post date:** [April 15, 2017, 10:05pm UTC](https://discourse.julialang.org/t/tasks-and-type-stability/3212/7 "2017-04-15T22:05:03Z")

</div>

@fengyang.wang, I concur. In 0.6.0-pre.beta.146, I do not see any type instabilities.
