Creating a dead simple CountDownLatch with ZIO

Amitay Horwitz
Feb 16 · 4 min read
Image for post
Image for post
Photo by Chris Barbalis on Unsplash

In this post I’ll explain what a CountDownLatch is, and how ZIO enables you to create concurrency primitives which are efficient, non-blocking and simple.

  • Note: I assume you have basic understanding of what ZIO is

Background

At Wix, we love testing. But testing concurrent code is often more difficult than writing it.

I recently needed to write a test which involves waiting until a number of async callbacks are called before making my assertion. More precisely, the system I’m testing involves async producer / consumer (or publish / subscribe) model, and the test looks something like this (with zio-test):

The problem here is that if the produceTo and consumeFrom functions actually run asynchronously my test will be flaky, because by the time I call records.get the result might still be empty.

We don’t like flaky tests. The simple solution is to poll, or retry the assertion at some constant interval until it succeeds. ZIO provides wonderful tools for such use cases, like the repeat combinator:

But this made the test much more cumbersome, and the polling strategy feels somewhat messy.

Looking back to Java

Java’s primary way of tackling concurrency is by using threads. However, writing multithreaded code is notoriously difficult and error prone. To make writing concurrent code more sane, there are many utilities available in the java.util.concurrent package. One of these is the CountDownLatch.

As described in the JavaDoc:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

A CountDownLatch is initialized with a given count. The await method block until the current count reaches zero due to invocations of the countDown method, after which all waiting threads are released and any subsequent invocations of await return immediately.

My use case seems like a perfect fit for a CountDownLatch, however, ZIO doesn’t provide one out of the box. It does provide other primitives that we can build on top of, such as Promise, Ref, Queue, Semaphore and others. So let’s try to create our own concurrent and non-blocking CountDownLatch using ZIO!

The API

The API we need is more simplified compared to Java’s CountDownLatch and looks something like this:

We can omit some of the original methods, such as await with timeout:

Because we could easily achieve these semantics using ZIO’s built-in combinators, which demonstrate the power of having a composable functional API:

For the actual implementation, all we need is a Ref to keep the current count, and a Promise to signal when the count reached 0. Creating a Ref and a Promise is an effectful operation, which means creating our CountDownLatch will also be effectful (which makes sense, because it keeps internal state).

With just a few lines of code, we have created our own CountDownLatch! Let’s rewrite our original test using our new utility:

Now we can easily synchronize the behaviour of our tests, leading to a more reliable and consistent test suite.

Conclusion

Once again ZIO proves its value when writing asynchronous and concurrent code. We created a simple and non-blocking CountDownLatch with very little code, which is valuable for making our test suite more robust.

Read about similar experiences from my colleagues:

Wix Engineering

Architecture, scaling, mobile and web development…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store