Skip to content

Latest commit

 

History

History
89 lines (72 loc) · 1.32 KB

parallel.md

File metadata and controls

89 lines (72 loc) · 1.32 KB

Scheduling parallel tasks with future

// You can edit this code!
// Click here and start typing.
package main

import (
	"errors"
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func parallelTask() error {
	fmt.Println("is parallel")
	// return task()
	return errors.New("failed at parallel task")
}
func task() error {
	n := rand.Intn(10)
	fmt.Println("doing work", n)
	time.Sleep(1 * time.Second)
	fmt.Println("done", n)
	return nil
}

func main() {
	start := time.Now()
	defer func() {
		fmt.Println(time.Since(start))
	}()

	parallelTask := func() chan error {
		err := <-Future(parallelTask)
		if err != nil {
			ch := make(chan error, 1)
			ch <- err
			close(ch)

			return ch
		}
		return All(Future(parallelTask), Future(parallelTask))
	}

	errCh := All(Future(task), Future(task), Future(task), parallelTask())
	for err := range errCh {
		fmt.Println("received", err)
	}
}

type Task func() error

func All(chans ...chan error) chan error {
	errCh := make(chan error)

	var wg sync.WaitGroup
	wg.Add(len(chans))

	for _, ch := range chans {
		go func(ch chan error) {
			defer wg.Done()
			for err := range ch {
				errCh <- err
			}

		}(ch)
	}

	go func() {
		wg.Wait()
		close(errCh)
	}()

	return errCh
}

func Future(task Task) chan error {
	ch := make(chan error)

	go func() {
		defer close(ch)
		ch <- task()
	}()

	return ch
}