Comments (2)
Hi @loganpowell ,
You have a few deadlocks here
Deadlock 1
Description
yield _I_.put("Clojure")
waits until a first brick is taken from the _I_
chan, but this will only happen when your namer
function is called (yield _I_.take()
). Because the namer
waits until yield _I_.put("Clojure")
yields a result, you are in a deadlock.
Solution
One way of fixing that issue (though not idiomatic of how CSP is supposed to be used) is to not wait for a process to take a brick from the _I_
channel:
co(function *() {
_I_.put("Clojure")
yield namer(_I_, _O_)
const fancy_name = yield _O_.take()
console.log("hello", fancy_name)
})
However, even with this, you'll run into the second deadlock.
Deadlock 2
Description
The namer
function waits for a brick to be taken from the _O_
channel (yield _O_.put(fancy_name)
). The only line of code that unlocks that wait is occurring after the namer
invocation. That's the second deadlock.
Solution
One way of fixing that issue (though not idiomatic of how CSP is supposed to be used) is to not wait for taking a brick from the _O_
channel in the namer
function. The new namer
function would look like this:
const namer = (_I_, _O_) => co(function *() {
const name = yield _I_.take() // This waits until a first brick is added on the _I_ channel.
const fancy_name = `${name}izer`
_O_.put(fancy_name)
})
Combined Solutions
If we put those 2 solutions together, the code looks like this:
const co = require('co')
const { Channel } = require("core-async")
const namer = (_I_, _O_) => co(function *() {
const name = yield _I_.take() // This waits until a first brick is added on the _I_ channel.
const fancy_name = `${name}izer`
_O_.put(fancy_name) // REMOVING DEADLOCK 2
})
const _I_ = new Channel()
const _O_ = new Channel()
co(function *() {
_I_.put("Clojure") // REMOVING DEADLOCK 1
yield namer(_I_, _O_)
const fancy_name = yield _O_.take()
console.log("hello", fancy_name)
})
Better Approach
However, as I briefly mentioned before, this is not idiomatic of CSP. Indeed, what if the namer
function is supposed to do more work after _O_.put(fancy_name)
and that work must happen after there is a confirmation that another process has taken that brick from the _O_
channel. We could make the same remark for the _I_.put("Clojure")
. What if we need to add a piece of work between _I_.put("Clojure")
and yield namer(_I_, _O_)
that can only be executed when there is confirmation that the "Clojure"
brick has been taken from the _I_
channel. This solution would have to be refactored.
Your original namer
function is fine. It works properly and does not contain deadlocks, but the way it is being used leads to deadlocks. So here is a suggestion of how your code could be re-written in what I think, IMHO, might be a more idiomatic CSP style.
const co = require('co')
const { Channel } = require("core-async")
// This is your original func
const namer = (_I_, _O_) => co(function *() {
const name = yield _I_.take() // This waits until a first brick is added on the _I_ channel.
const fancy_name = `${name}izer`
yield _O_.put(fancy_name) // This waits until a first request for a brick is emitted on the _O_ channel.
})
const _I_ = new Channel()
const _O_ = new Channel()
// 'namer' does stuff asynchronously
co(function *() {
console.log(`Doing some work before 'namer' starts`)
yield namer(_I_, _O_)
console.log(`Doing some more work now that 'namer' is done`)
})
// Asynchronously do things each time a brick is added to the _O_ channel.
co(function *() {
const fancy_name = yield _O_.take()
console.log("hello", fancy_name)
})
// Asynchronously do things each time a brick is taken from the _I_ channel.
co(function *() {
yield _I_.put("Clojure") //?
console.log(`Great, somebody took the 'Clojure' brick. I can do other awesome stuff now.`)
})
If you're craving for more Clojure stuff in JS (e.g., combining CSP patterns with transmuters), then a more mature library is js-csp. The only reason I built core-async
instead of using js-csp is that I needed the alts
function.
I hope my explanation shed some light on your problem.
Cheers,
Nic
from core-async.
Dude, just awesome all around.
from core-async.
Related Issues (3)
- Holy mackerel! HOT 1
- Thought you'd like this HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from core-async.