Skip to content

Instantly share code, notes, and snippets.

@jhidajat
Last active May 14, 2020 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhidajat/61b7247d72f633d3b88f3a69cc91aaa5 to your computer and use it in GitHub Desktop.
Save jhidajat/61b7247d72f633d3b88f3a69cc91aaa5 to your computer and use it in GitHub Desktop.
func ProcessNode(node, spec) {
...
return ContentNodeWithDisplay{...}
}
type ProcessArgs {
node *ContentNode
spec ProcessNodeSpec
}
func Workers(task func(ProcessArgs), completionCallback func(), workerCount int) chan ProcessArgs {
arguments := make(chan ProcessArgs)
completedCounter := make(chan bool)
for i:=0; i<workerCount; i++ {
go func() {
for {
arg, success := <-arguments
if !ok {
completedCounter <- true
return
}
task(arg.node, arg.spec)
}
}()
}
// Create annother go-routine dedicated to keep track of completed processNode() go-routines
go func() {
for i:=0; i<workerCount; i++ {
<-completedCounter // blocking
}
// executed once there is no more blocking go-routine in the counter channel
// (i.e. all go-routines are completed)
completionCallback()
}()
return arguments // so that arguments can be exposed to processNodes
}
func processNodes(nodes, spec) {
validNodes := make([]*ContentNode, 0, len(nodes))
for _, node := range nodes {
if node != nil {
validNodes = append(validNodes, node)
}
}
// only one message is pushed and pulled. Intention is
// to block main go-routine from exiting before completion
mainCanExit := make(chan bool)
workers := Workers(
// task invoked by go-routine
func(args ProcessArgs) {
ProcessNode(args.node, args.spec)
},
// completion callback
func() {
mainCanExit<-true
})
for _, node := range(validNodes) {
workers <- ProcessArgs(node, spec)
}
// close channel and processNodes() can finally exit
close(workers)
<-mainCanExit // blocking
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment