2015-09-24 10 views
2

У меня есть два однонаправленных канала: core.asyncClojure - core.async объединить однонаправленный канал

  • канала из может только put!
  • канал может только take!

И поскольку это ClojureScript блокировка операции недоступны. Я хотел бы сделать один двунаправленный (входной) канал из этих двух (в и из).

(def in (async/chan)) 
    (def out (async/chan)) 
    (def in-out (io-chan in out)) ;; io or whatever the solution is 

    (async/put! in "test") 
    (async/take! ch (fn [x] (println x))) ;; should print "test" 
    (async/put! ch) ;; put into ch is equivalent to putting into `out` 

Я пытался что-то вроде следующего (не работает):

(defn io-chan [in-ch out-ch] 
    (let [io (chan)] 
    (go-loop [] 
     (>! out-ch (<! io)) 
     (>! io (<! in-ch)) 
     (recur)) 
    io)) 

Схема может помочь:

out        in-out 
---------------> (unused)   
<---------------    <--------------- 

    in 
---------------->    ----------------> 
<---------------- (unused) 

Кроме того, закрытие двунаправленного канала следует закрыть оба канала, лежащие в основе.

Is is?

+0

Извините, я не использую ваш случай использования, возможно, вы могли бы добавить пример кода того, что хотите? –

+0

@ ValentinWaeselynck Я отредактировал мой вопрос, надеюсь, теперь это имеет смысл. – nha

+0

Все еще не уверен, что получаю:/вы указываете 6 названий каналов в своем описании (A, B, in, out, io, ch). помогло бы, если бы вы объединили это –

ответ

1

Если я правильно понимаю ваш вариант использования, я считаю, что то, что вы пытаетесь сделать, - это просто одноканальная работа.

С другой стороны, если вы пытаетесь представить канал-подобный интерфейс для композита из нескольких каналов (например, какой-то процесс принимает данные от in, обрабатывает его и выводит результат на out) , тогда вы всегда можете реализовать право protocols (в случае ClojureScript, cljs.core.async.impl.protocols/ReadPort и cljs.core.async.impl.protocols/WritePort).

Я бы лично не рекомендовал. Оставляя в стороне тот факт, что вы будете полагаться на детали реализации, я не считаю, что каналы core.async предназначены для инкапсуляции для процессов, только как точки связи между ними.Поэтому в этом случае используйте только входной канал для производителей и выходного канала для потребителей.

+0

Речь идет о связи в моем случае (клиент -> сервер и сервер -> клиент). Имеет ли смысл внедрение этих протоколов в этом случае? – nha

+0

ах, поэтому один канал предназначен для отправки на сервер, а другой для чтения с сервера, не так ли? Поскольку у вас одностороннее чтение, а одностороннее письмо вовсе не означает, что вы должны делать это на одном и том же порту (не компилируйте их :)). И опять же, эти протоколы не являются частью публичного API, опасно полагаться на них. Я бы определенно пошел с двумя каналами. –

+0

Да точно :) Я полностью понимаю суть непубличного API, но я не уверен, что понимаю, почему я не должен их компилировать? – nha

1

Вашего пример показывает поток пояснит, как это:

io ---> out-ch ---> worker ---> in-ch ---> io 
^-------------------------------------------* 

Если мы предположим, что работник читает in-ch и пишет out-ch то, возможно, эти два канала обращены в примере. если работник делает обратное, то это правильно. для предотвращения циклов важно, чтобы вы использовали небуферизованные очереди, чтобы вы не слышали, как ваши собственные сообщения повторяются обратно к себе.

В качестве побочного примечания нет таких направлений, как однонаправленные и двунаправленные каналы. вместо этого есть буферизованные и небуферированные каналы. Если мы говорим о буферизованном канале, тогда, когда мне есть что сказать, я припаркую, пока вы не слушаете канал, а затем, когда вы будете готовы его услышать, я поместил свое сообщение в канал, и вы его получите. Затем, чтобы получить ответ, я припаркован, пока вы не будете готовы отправить его, и как только вы это сделаете, вы поместите его на канал, и я получаю его из канала (все сразу). Это похоже на двунаправленный канал, хотя на самом деле это просто, что небуферизованные каналы координируются таким образом.

Если канал буферизуется, тогда я могу получить свое собственное сообщение обратно с канала, потому что я закончу его размещение на канале, а затем буду готов принять ответ, прежде чем вы сможете даже получить исходное сообщение. Если вам нужно использовать буферные каналы, как это, то используйте два из них, по одному для каждого направления, и они будут «чувствовать» как однонаправленные каналы.

+0

Спасибо. Я должен был упомянуть, что «рабочий» на самом деле является сервером, и да, однонаправленные каналы не существуют как таковые, однако в моем случае они должны быть (в зависимости от средств связи). – nha

+1

Возможно, шаблон отправки канала ответа с запросом будет соответствовать вашей ситуации, но, скорее всего, это предположение. –