# Strange error with coroutines

**URL:** <https://discourse.julialang.org/t/strange-error-with-coroutines/20815>\
**Category:** General Usage\
**Created:** [February 15, 2019, 9:58am UTC](https://discourse.julialang.org/t/strange-error-with-coroutines/20815 "2019-02-15T09:58:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![zweiglimmergneis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zweiglimmergneis/32/7892_2.png) [@zweiglimmergneis](https://discourse.julialang.org/u/zweiglimmergneis)\
**Post date:** [February 15, 2019, 9:58am UTC](https://discourse.julialang.org/t/strange-error-with-coroutines/20815/1 "2019-02-15T09:58:45Z")

</div>

I get an error filling a an array using two different `Channel`s. Surprisingly, the error disappears by adding a debug `println` statement. I tried to set up a smaller example. However, with only one `Channel` the error could not be reproduced.

```julia
"""
    deliver(c::Channel, pile::Vector{Int}, r::UnitRange{Int})

Take a card from range `r` in `pile`.
"""
function deliver(c::Channel, pile::Vector{Int}, r::UnitRange{Int})
    for i in r
        put!(c, pile[i])
    end
end

"""
    collectlr!(pile::Vector{Int}, c1::Channel, c2::Channel)

Collect cards randomly form `c1` or `c2`. If one of them is exhausted return the other.
"""

function collectlr!(dest::Vector{Int}, c1::Channel, c2::Channel)
    k = 0
    for i in 1:lastindex(dest)
        if !isready(c1)
           return(c2, i)
        else
            rlr = rand()
            if rlr < 0.5
                dest[i] = take!(c1)
                #println("c1: ", dest[i])
            elseif !isready(c2)
                return(c1, i)
            else
                dest[i] = take!(c2)
                #println("c2: ", dest[i])
            end
        end
        k = i
    end
    return(c1, k)
end

function mix!(dest::Vector{Int}, source::Vector{Int})
    p = lastindex(source)
    hp = div(p, 2)
    c1 = Channel(c -> deliver(c, source, 1:hp))
    c2 = Channel(c -> deliver(c, source, hp + 1:p))
    (c, i) = collectlr!(dest, c1, c2)
    for j in i:lastindex(dest)
        dest[j] = take!(c)
    end
    dest
end

```

Execution:

```julia
julia> p1 = collect(1:8); p2 = zeros(Int, 8); mix!(p2, p1)
ERROR: InvalidStateException("Channel is closed.", :closed)
Stacktrace:
 [1] try_yieldto(::typeof(Base.ensure_rescheduled), ::Base.RefValue{Task}) at ./event.jl:196
 [2] wait() at ./event.jl:255
 [3] take_unbuffered(::Channel{Any}) at ./channels.jl:338
 [4] take! at ./channels.jl:315 [inlined]
 [5] mix!(::Array{Int64,1}, ::Array{Int64,1}) at ./REPL[4]:8
 [6] top-level scope at none:0

```

Uncomment the `println`-statements and get:

```julia
julia> p1 = collect(1:8); p2 = zeros(Int, 8); mix!(p2, p1)
c2: 5
c2: 6
c2: 7
c1: 1
c2: 8
8-element Array{Int64,1}:
 5
 6
 7
 1
 8
 2
 3
 4

```

Thanks for hints!

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [February 15, 2019, 1:40pm UTC](https://discourse.julialang.org/t/strange-error-with-coroutines/20815/2 "2019-02-15T13:40:58Z")

</div>

I think you need `yield()` calls (e.g. after the “concurrent” `take!`). `Base.println` uses the same libuv event loop as the Channels, so it does the yield for you. (You can use `Core.print` to diagnose tasks without interfering.)

---

<div class="post-metadata">

**Author:** ![zweiglimmergneis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zweiglimmergneis/32/7892_2.png) [@zweiglimmergneis](https://discourse.julialang.org/u/zweiglimmergneis)\
**Post date:** [February 15, 2019, 1:49pm UTC](https://discourse.julialang.org/t/strange-error-with-coroutines/20815/3 "2019-02-15T13:49:17Z")

</div>

Yes, works! Thanks for the hint and the info about the event loop!

I tried another version using `Iterators.Stateful`. This seems to be more efficient in this case.
