0

I have some core.async code with a pipeline of two chans and three nodes :

  • a producer - function that puts values into chan1 with >!! (it's not in a go-block but the function is called from inside a go-loop)

  • a filter - another function that's not in a go-block but is called within a go-loop, which pulls items from chan1 (with <!!), does a test and if the test passes pushes them onto chan2 (with >!!)

  • a consumer - an ordinary loop that pulls n values of chan2 with

This code works as expected when I run it as a simple program. But when I copy and paste it to work within a unit-test, it freezes up.

My test code is roughly

(deftest a-test 
  (testing "blah"  
    (is (= (let [c1 (chan)
                 c2 (chan)                 
                 gen (make-generator c1)
                 filt (make-filter c1 c2)
                 result (collector c2 10) ]
              result)
           [0 2 4 6 8 10 12 14 16 18 20]))
))

where the generator creates a sequence of integers counting up from zero and the filter tests for evenness.

As far as I can tell, the filter is able to pull the first value from the c1, but is blocked waiting for a second value. Meanwhile, the generator is blocking while waiting to push its next value into c1.

But this doesn't happen when I run the code in a simple stand-alone program.

So, is there any reason that the unit-test framework might be interfering or causing problems with the threading management that core.async is providing? Is it possible to do unit-testing on async code like this?

I'm concerned that I'm not running the collector in any kind of go-block or go-loop so presumably it might be blocking the main thread. But equally, I presume I have to pull all the data back into the main thread eventually. And if not through that mechanism, how?

6
  • 1
    Why would you use blocking puts and takes within go-blocks? This is usually a bad idea. Commented Sep 5, 2016 at 17:01
  • I'm not inside a go-block ... I'm inside a function that's called from a go-loop .. but Clojure doesn't seem to let me use <! and >! there. Commented Sep 5, 2016 at 17:08
  • Maybe I'm not understanding async. What I want is a separate thread for the generator and filter objects. But I don't mind them blocking their own thread when waiting for the next input or for the output channel to be available. But i'm mystified how I'm finding myself deadlocked here. Commented Sep 5, 2016 at 17:10
  • 1
    did you try using (async/thread (loop [... instead of (async/go-loop [...? Commented Sep 5, 2016 at 17:52
  • no ... let me have a look ... Commented Sep 5, 2016 at 18:08

1 Answer 1

2

While using blocking IO within go-blocks/go-loops isn't the best solution, thread macro may be better fit here. It will execute passed body on separate thread, so you may freely use blocking operations there.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.