let mix ta tb =
  let a_buffer = ref None in
  let name =
    sprintf "(mix <%s> <%s>)"
      Option.(value ~default:"" (name ta))
      Option.(value ~default:"" (name tb)) in
  make_general ~name ()
    ~feed:(fun (a, b) -> feed ta a; feed tb b)
    ~stop:(fun () -> stop ta; stop tb)
    ~next:(fun () ->
      begin match !a_buffer with
      | None ->
        begin match next ta with
        | `output oa ->
          begin match next tb with
          | `output ob -> `output (`both (oa, ob))
          | `not_ready -> a_buffer := Some oa; `not_ready
          | `end_of_stream -> `end_of_stream
          end
        | `not_ready -> `not_ready
        | `end_of_stream ->
          begin match next tb with
          | `output ob -> `output (`right ob)
          | `not_ready -> `not_ready
          | `end_of_stream -> `end_of_stream
          end
        end
      | Some oa ->
        begin match next tb with
        | `output ob -> a_buffer := None`output (`both (oa, ob))
        | `not_ready -> `not_ready
        | `end_of_stream -> a_buffer := None`output (`left oa)
        end
      end)