66package async
77
88type Task func () interface {}
9+ type STask func (interface {}) interface {}
910type Channel chan interface {}
1011type Result []interface {}
1112
13+ // Reference: https://blog.golang.org/pipelines
14+ // Reference: https://en.wikipedia.org/wiki/Moore%27s_law
15+ // https://en.wikipedia.org/wiki/Amdahl%27s_law
16+
1217type Promise struct {
1318 //TODO:
1419 //Context - Cancel, Timeout
@@ -17,9 +22,12 @@ type Promise struct {
1722 //Can I use map for tasks? It will be easy to associate results with keys
1823}
1924
20- func (p * Promise ) All (tasks []Task ) Result {
21- // can not use buffer channels, because not able to maintain sequence
22- // using channel slice
25+ //
26+ // parallel execution of all tasks
27+ //
28+ func (p * Promise ) Parallel (tasks []Task ) Result {
29+ // can not use buffer channels, because not able to maintain output sequence
30+ // using slice channels
2331 workers := make ([]Channel , 0 , len (tasks ))
2432 for _ , task := range tasks {
2533 workers = append (workers , func () Channel {
@@ -37,5 +45,64 @@ func (p *Promise) All(tasks []Task) Result {
3745 for _ , result := range workers {
3846 out = append (out , <- result )
3947 }
48+
4049 return out
4150}
51+
52+ //
53+ // sequential execution of all tasks
54+ //
55+ func (p * Promise ) Series (tasks []Task ) (out interface {}, err error ) {
56+ // unbuffered channel
57+ worker := make (Channel )
58+ defer close (worker )
59+
60+ for _ , task := range tasks {
61+ // need to check the benefits of executing tasks on another go routine
62+ go func (task Task ) {
63+ worker <- task ()
64+ }(task )
65+
66+ out = <- worker
67+
68+ if err = isError (out ); err != nil {
69+ out = nil
70+ break
71+ }
72+ }
73+
74+ return
75+ }
76+
77+ //
78+ // sequential execution of all tasks, but output of all tasks will be input for next task
79+ //
80+ func (p * Promise ) Waterfall (tasks []STask ) (out interface {}, err error ) {
81+ // unbuffered channel
82+ worker := make (Channel )
83+ defer close (worker )
84+
85+ for _ , task := range tasks {
86+
87+ go func (task STask ) {
88+ worker <- task (out )
89+ }(task )
90+
91+ out = <- worker
92+
93+ if err = isError (out ); err != nil {
94+ out = nil
95+ break
96+ }
97+ }
98+
99+ return
100+ }
101+
102+ func isError (val interface {}) (err error ) {
103+ switch val .(type ) {
104+ case error :
105+ err = val .(error )
106+ }
107+ return
108+ }
0 commit comments